diff --git a/.gitignore b/.gitignore index d2d2f13bd..7d8a08c75 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ *.dSYM .*.sv[a-z] .*.sw[a-z] +.su[a-z] .DS_Store .sv[a-z] .sw[a-z] diff --git a/1984/README.md b/1984/README.md index 40b360df3..9cc6b6411 100644 --- a/1984/README.md +++ b/1984/README.md @@ -1,14 +1,19 @@ -In 1984, the first contest was held. The name of the contest was simply -``Obfuscated C Code Contest''. +# First Obfuscated C Code Contest -Look at the README.md file for the given winner for information on how to -compile the winner and how to run the winning program. Look at the winning -source and try to figure how it does what it does! You may then wish to look at -the Author's remarks for even more details. +In [1984](/years.html#1984), the first contest was held. The name of the contest was simply +"`Obfuscated C Code Contest`". + +Look at the `README.md`file for the given winner for information on how to +compile the entry and how to run the winning program. Look at the winning +source and try to figure how it does what it does! This year we only had +remarks from two authors but which came years later. Restrictions against machine dependent code were not in the [rules](rules.txt) in 1984. The source file size restriction was only 512 bytes. Rules and results -were posted to net.lang.c and net.unix-wizards. +were posted to [net.lang.c](https://groups.google.com/g/net.lang.c) and +[net.unix-wizards](https://groups.google.com/g/net.unix-wizards). The contest +was announced in a [net.lang.c +post](https://groups.google.com/g/net.lang.c/c/lx-TAuEyeRI/m/HdOOnNx6LC0J). =-= diff --git a/1984/anonymous/README.md b/1984/anonymous/README.md index 5ac31d03a..22ccd5ad9 100644 --- a/1984/anonymous/README.md +++ b/1984/anonymous/README.md @@ -1,22 +1,25 @@ # Dishonorable mention - Anonymous +Anonymous ## To build: - make all +```sh +make all +``` ## To run: - ./anonymous - +```sh +./anonymous +``` [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed this to work under macOS. The fix was to prototype `read()` prior to being defined and not using `int, int, int` as the entry does. Instead the second arg is a `void *`. -In the `read()` function which actually calls `write(2)` the `i` (which is the -`void *` has to be cast to an `int`. This solves the problem. Thank you Cody for +In the `read()` function (which actually calls `write(2)`) the `i` (which is the +`void *`) has to be cast to an `int`. This solves the problem. Thank you Cody for your assistance! @@ -47,7 +50,7 @@ Some years after this entry was published we asked the author if they still wished to remain anonymous and they said: > Yes, I want to keep my anonymity. But you can tell them that I am well known -for my connection to the C language.' +for my connection to the C language. ### On the famous tattoo (see above): @@ -63,10 +66,10 @@ Landon Curt Noll, the one who told the author about the tattoo, wrote back: ### Regrets: Landon Curt Noll wrote that the author, if they had to do it over again, regrets not -making the program a one-liner and not moving the "int i" into an arg of main +making the program a one-liner and not moving the `int i` into an arg of main (so that the line would have started with main). On the other hand the author -likes the "two line look" and the way hell o was split. :-) And they like the -fact that it ends in a smily face: ;} +likes the "two line look" and the way `hell o` was split. :-) And they like the +fact that it ends in a smily face: `;}` ## Copyright and CC BY-SA 4.0 License: diff --git a/1984/decot/Makefile b/1984/decot/Makefile index 9eb6160d8..d6709ab28 100644 --- a/1984/decot/Makefile +++ b/1984/decot/Makefile @@ -137,6 +137,9 @@ ${PROG}: ${PROG}.c alt: data ${ALT_TARGET} @${TRUE} + +${PROG}.alt: ${PROG}.alt.c + ${CC} ${CFLAGS} -traditional-cpp $< -o $@ ${LIBS} # data files # data: ${DATA} diff --git a/1984/decot/README.md b/1984/decot/README.md index 7e5bf7302..ed0215d26 100644 --- a/1984/decot/README.md +++ b/1984/decot/README.md @@ -1,19 +1,23 @@ # Second place award -Dave Decot +Dave Decot ## To build: - make all +```sh +make all +``` + +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed this to not +require `-traditional-cpp` which not all compilers support (clang does not +support it for example). Clang is also more strict about the args' types in +`main()` and this was also a problem that Cody fixed, making it work with both +clang and gcc. For the original code with the gcc fix described below, see the +alternate code section below. Thank you Cody for your assistance! Originally [Yusuke Endoh](/winners.html#Yusuke_Endoh) supplied a patch so that this entry would compile with gcc - but not clang - or at least some versions. -Thank you Yusuke! [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) -noticed this did not work under fedora linux and it definitely didn't work with -macOS as it required a compiler that supports `-traditional-cpp` which clang -does not. Clang also requires that the second and third arguments to main be a -`char **`. Cody fixed both problems and now it works under both macOS and linux -- clang and gcc. Thank you Cody for your assistance! +Thank you Yusuke! ## To run: @@ -21,13 +25,13 @@ does not. Clang also requires that the second and third arguments to main be a ./decot ``` -### Alternative code: +### Alternate code: -The alternative code, [decot.alt.c](decot.alt.c), is the fix that Cody made to -the version that does require `-traditional-cpp` and still runs afoul with -clang's requirement for the second and third arguments to main() being a `char -**` (the fixed version's main() only has one arg, an int). It is a minor fix to -Yusuke's fix. Thank you Yusuke and Cody! +The alternate code, [decot.alt.c](decot.alt.c), is the original code that +requires `-traditional-cpp` and will also run afoul with clang's requirement for +the second and third arguments to main() being a `char **` (the fixed version's +main() only has one arg, an int). It is a minor fix to Yusuke's fix. Thank you +Yusuke and Cody! To try this version: @@ -43,7 +47,7 @@ This program prints out a string of garbage. The judges also offer this one comment: understand remarks! -### Historical comments: +### Historical remarks: Some new (in 1984) compilers disliked line 15 of the original source, so we changed it from: @@ -65,7 +69,7 @@ To see what we mean look at the source file in the ## Author's remarks: -No comments were provided by the author. +No remarks were provided by the author. ## Copyright and CC BY-SA 4.0 License: diff --git a/1984/laman/README.md b/1984/laman/README.md index 263d4d3c1..62ba979a8 100644 --- a/1984/laman/README.md +++ b/1984/laman/README.md @@ -1,14 +1,18 @@ # Third place -Mike Laman +Mike Laman ## To build: - make all +```sh +make all +``` ## To run: - ./laman +```sh +./laman +``` ### INABIAF - it's not a bug it's a feature :-) @@ -22,9 +26,11 @@ arg. The program accepts ONE POSITIVE argument. Seeing is believing, so try things like: - ./laman 4 - ./laman 9 - ./laman 16 +```sh +./laman 4 +./laman 9 +./laman 16 +``` This code should run you in circles. @@ -33,19 +39,23 @@ This code should run you in circles. Some new compilers dislike lines 6 and 10 of the source, so we changed them from: - ;++f)a[ b<<5|c] =d++,b+ =e;for( f=0;f NOTE: If your machine is not a Vax-11 or pdp-11, this program will > not execute correctly. In later years, machine dependent > code was discouraged. -## Alternative code: +### Alternative code: [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) added the alternative code which lets you run this on other systems. He notes though that this was only a slight fix and enhancement to the change in the [faq](/faq.md). Thank you Cody for your assistance! -### To build: +#### To build: - make alt +```sh +make alt +``` -### To run: +#### To run: - ./mullender.alt [microseconds] +```sh +./mullender.alt [microseconds] +``` -The default microseconds is 10000. This ability is so you can experiment with +The default microseconds is 10000. This feature is so you can experiment with different speeds in between writes. It can be useful if your CPU is too slow or too fast. -BTW: is there such a thing as too fast a CPU ? :-) actually yes for certain code -which is probably not as uncommon as you think :-) ). +BTW: is there such a thing as too fast a CPU ? :-) Actually yes for certain code +which is probably not as uncommon as you think :-). Note that it is an int and it uses `atoi()` which does NOT check for overflow! In fact it's argc itself. -## Try: +#### Try: - ./mullender.alt +```sh +./mullender.alt - ./mullender.alt 5000 +./mullender.alt 5000 - ./mullender.alt 500 +./mullender.alt 500 - ./mullender.alt 20000 +./mullender.alt 20000 + +./mullender.alt 100000 +``` What happens if you hit enter after it writes a line of output? @@ -84,7 +96,7 @@ BTW: this remains my (Landon Curt Noll's) all time favorite entries! ## Author's remarks: -These comments, found at +These remarks, found at [https://lainsystems.com/posts/exploring-mullender-dot-c/](https://lainsystems.com/posts/exploring-mullender-dot-c/), were provided by Sjoerd Mullender years later. We thank the author of the article for the quote! @@ -123,11 +135,11 @@ would fit, some as an ASCII character. The rest is history. Since this was the first contest, we hadn't seen any old entries, nor had any of -the other contestants. Of course we knew about #define and tricks you could do +the other contestants. Of course we knew about `#define` and tricks you could do with that, but we didn't need that for this program. In fact, we made it as -“standard” as possible. At the time there was this program called “cb” for C +“standard” as possible. At the time there was this program called `cb` for C beautifier which would re-indent your program to make the layout look better. Our -program is idempotent under cb. +program is idempotent under `cb`. ## Copyright and CC BY-SA 4.0 License: diff --git a/1985/README.md b/1985/README.md index 49f54f9b3..43853beae 100644 --- a/1985/README.md +++ b/1985/README.md @@ -1,16 +1,19 @@ -1985 marked the second year of the International Obfuscated C Code Contest. +# [1985](/years.html#1985) marked the second year of the International Obfuscated C Code Contest. -Look at the README.md file for the given winner for information -on how to compile the winner and how to run the winning program. +Look at the `README.md` file for the given winner for information +on how to compile the entry and how to run the winning program. Look at the winning source and try to figure how it does what it does! You may then wish to look at the Author's remarks for even more details. Hints against machine dependent code were added to the [rules](rules.txt) to -avoid another 1984 style winner ([1984/mullender](../1984/mullender)). Rules and -results were posted to net.lang.c and net.unix-wizards. Larry Bassel was -invited to help in the judging. Awards were given to 5 classes of programs +avoid another 1984 style winner ([1984/mullender](../1984/mullender)). +[Rules](rules.txt) and [results](/years.html#1985) were posted to +[net.lang.c](https://groups.google.com/g/net.lang.c) and +[net.unix-wizards](https://groups.google.com/g/net.unix-wizards). Larry Bassel +was invited to help in the judging. Awards were given to 5 classes of programs since we were unable to select only the best 4. + =-= Copyright (c) 1985, Landon Curt Noll & Larry Bassel. diff --git a/1985/applin/Makefile b/1985/applin/Makefile index 1c001b094..d0f1abe41 100644 --- a/1985/applin/Makefile +++ b/1985/applin/Makefile @@ -61,7 +61,7 @@ CDEFINE= # Include files that are needed to compile # -CINCLUDE= +CINCLUDE= -include unistd.h # Optimization # diff --git a/1985/applin/README.md b/1985/applin/README.md index 707200815..0715ec3ca 100644 --- a/1985/applin/README.md +++ b/1985/applin/README.md @@ -1,20 +1,29 @@ # Best one liner -Jack Applin [with help from Robert Heckendorn] +Jack Applin [with help from Robert Heckendorn] + ## To build: - make all +```sh +make all +``` ## Try: - ./applin - +```sh +./applin +``` NOTE: [Yusuke Endoh](/winners.html#Yusuke_Endoh) provided a patch to get this to -not issue a bus error. Thank you Yusuke! [Cody Boone -Ferguson](/winners.html#Cody_Boone_Ferguson) noted that this entry does not work -under macOS. Try it out and see for yourself what happens! +not issue crash and [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) +fixed this to work with macOS. The problem with the crash is that it +destructively rewrites string literals but with `strdup()` it's safe. For macOS +it's because there was no prototype for `execlp()` and macOS has problems with +missing prototypes for some functions (this was also seen when Cody fixed +[1984/anonymous](/1984/anonymous/anonymous.c) for macOS as well though that fix +was more complicated). Ironically this fix was discovered through linux! Thank +you Yusuke and Cody for your help! ## Judges' remarks: @@ -24,7 +33,7 @@ certainly takes its time saying hello. ## Author's remarks: -No comments were provided by the author. +No remarks were provided by the author. ## Copyright and CC BY-SA 4.0 License: diff --git a/1985/august/README.md b/1985/august/README.md index 410c4ea9f..983941e1c 100644 --- a/1985/august/README.md +++ b/1985/august/README.md @@ -1,26 +1,32 @@ # The most obscure program -Lennart Augustsson - +Lennart Augustsson + ## To build: - make all +```sh +make all +``` ## To run: - ./august +```sh +./august +``` ## Try: - - ./august | head -n 10 +```sh +./august | head -n 10 +``` If you have the `primes(6)` tool (sometimes part of BSD Games) you can see what of the output in the first N (say 15) lines are primes: - while read -r n ; do primes "$n" $((n + 1)) ; done < <((./august | head -n 15 )) - +```sh +while read -r n ; do primes "$n" $((n + 1)) ; done < <((./august | head -n 15 )) +``` ## Judges' remarks: @@ -34,7 +40,7 @@ memory or until they sell your computer, which ever comes first. ## Author's remarks: -No comments were provided by the author. +No remarks were provided by the author. ## Copyright and CC BY-SA 4.0 License: diff --git a/1985/lycklama/Makefile b/1985/lycklama/Makefile index ce02663ac..de594d275 100644 --- a/1985/lycklama/Makefile +++ b/1985/lycklama/Makefile @@ -58,7 +58,7 @@ ARCH= # Defines that are needed to compile # -CDEFINE= +CDEFINE= -DZ=0 # Include files that are needed to compile # diff --git a/1985/lycklama/README.md b/1985/lycklama/README.md index 024579b1c..e0b7e64ad 100644 --- a/1985/lycklama/README.md +++ b/1985/lycklama/README.md @@ -1,6 +1,6 @@ # The strangest appearing program -Ed Lycklama +Ed Lycklama ## To build: @@ -13,7 +13,20 @@ make all modern compilers. In the past 'define' in `#define` could even be defined but to get this to work on modern systems Cody changed the `#o` lines to `#define`. The `lycklama.alt.c` is the original source code as it provides some fun input for -the entry. +the entry. Thank you Cody! With a tip from [Yusuke +Endoh](/winners.html#Yusuke_Endoh) it was indirectly noticed that if one slows +down the call to `write()` one can see some fun output that's not visible with +modern systems so Cody added a call to `usleep()`. The default time is `0` +which disables it (in order to make it as close to original as possible; an alt +version already exists mostly for fun output). In order to change the speed (try +500 or 700) do: + +```sh +make CDEFINE+="-DZ=700" clobber all +``` + +Thank you Yusuke! + ## Try: @@ -55,7 +68,7 @@ The program itself looks like tty noise. ## Author's remarks: -No comments were provided by the author. +No remarks were provided by the author. ## Copyright and CC BY-SA 4.0 License: diff --git a/1985/lycklama/lycklama.c b/1985/lycklama/lycklama.c index 3bb0f7462..72a594f36 100644 --- a/1985/lycklama/lycklama.c +++ b/1985/lycklama/lycklama.c @@ -9,7 +9,7 @@ #define o_ main #define o__ if #define oo_ 0 -#define _o(_,__,___)(void)___o(_,__,ooo(___)) +#define _o(_,__,___)(void)___o(_,__,ooo(___),Z&&usleep(Z)) #define __o (o_o_<<((o_o_<<(o_o_< ## To build: - make all +```sh +make all +``` ## To run: - ./applin +```sh +./applin +``` ## Try: - sh applin.c +```sh +sh applin.c - ./applin +./applin +``` ## Judges' remarks: @@ -30,7 +34,7 @@ compilers as well as executable by the Bourne shell! ## Author's remarks: -No comments were provided by the author. +No remarks were provided by the author. ## Copyright and CC BY-SA 4.0 License: diff --git a/1986/august/README.md b/1986/august/README.md index 06605cdd5..748a80ca5 100644 --- a/1986/august/README.md +++ b/1986/august/README.md @@ -1,20 +1,19 @@ # Best complex task done in a complex way -Lennart Augustsson -Dept. of Comp. Sci. -Chalmers University of Technology, -412 96 Gothenburg -Sweden +Lennart Augustsson + ## To build: - make all - - +```sh +make all +``` ## Try: - ./august +```sh +./august +``` NOTE: this entry is very likely to core dump after its output. @@ -31,7 +30,7 @@ enough to try and parse it correctly. ## Author's remarks: -No comments were provided by the author. +No remarks were provided by the author. ## Copyright and CC BY-SA 4.0 License: diff --git a/1986/bright/README.md b/1986/bright/README.md index 53f3f7304..b85aab2da 100644 --- a/1986/bright/README.md +++ b/1986/bright/README.md @@ -1,21 +1,26 @@ # Most useful obfuscation -Walter Bright +Walter Bright ## To build: - make all +```sh +make all +``` ## To run: - ./bright some_file +```sh +./bright some_file +``` ## Try: - ./bright bright.c - - ./bright bright +```sh +./bright bright.c +./bright bright +``` ## Judges' remarks: @@ -28,7 +33,7 @@ maintain the Bourne shell! :-} ## Author's remarks: -No comments were provided by the author. +No remarks were provided by the author. ## Copyright and CC BY-SA 4.0 License: diff --git a/1986/hague/README.md b/1986/hague/README.md index 13e8d8a26..010d48956 100644 --- a/1986/hague/README.md +++ b/1986/hague/README.md @@ -1,13 +1,13 @@ # Worst abuse of the C preprocessor -Jim Hague -University of Kent at Canterbury -Canterbury, Kent +Jim Hague UK ## To build: - make all +```sh +make all +``` NOTE: this entry uses gets() so you might get a warning about this when @@ -15,15 +15,19 @@ compiling and running this program with some systems. ## To run: +```sh ./hague # enter some text +``` ## Try: - ./hague - IOCCC - International Obfuscated C Code Contest - Jim Hague +```sh +./hague +IOCCC +International Obfuscated C Code Contest +Jim Hague +``` ## Judges' remarks: @@ -35,13 +39,13 @@ others. This program was selected for the 1987 t-shirt collection. Think Morse code when you ponder this program. Note how use of -similar variables can be obfuscating! The author notes that this +similar variables can be obfuscating! The author noted that this program implements the international Morse standard. Now for extra credit, what Morse message does the program spell out? ## Author's remarks: -No comments were provided by the author. +No remarks were provided by the author. ## Copyright and CC BY-SA 4.0 License: diff --git a/1986/holloway/README.md b/1986/holloway/README.md index ba6b76a93..06e540779 100644 --- a/1986/holloway/README.md +++ b/1986/holloway/README.md @@ -1,14 +1,13 @@ # Best simple task performed in a complex way Bruce Holloway -Digital Research, Inc. -Monterey, CA -USA +US ## To build: - make all - +```sh +make all +``` [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed this to compile and work with clang (it already worked with gcc). The problem was that @@ -20,7 +19,9 @@ Cody for your assistance! ## Try: - ./holloway +```sh +./holloway +``` ## Judges' remarks: @@ -32,7 +33,7 @@ this version as the first C program! ## Author's remarks: -No comments were provided by the author. +No remarks were provided by the author. ## Copyright and CC BY-SA 4.0 License: diff --git a/1986/marshall/README.md b/1986/marshall/README.md index 7711ad36e..744b8c6e9 100644 --- a/1986/marshall/README.md +++ b/1986/marshall/README.md @@ -1,14 +1,12 @@ # Best layout -Eric Marshall -System Development Corporation, a Burroughs Company -P.O. Box 517 -Paoli, PA. -19301 +Eric Marshall ## To build: - make all +```sh +make all +``` [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) got this to @@ -20,7 +18,9 @@ Cody for your help! ## Try: - ./marshall +```sh +./marshall +``` # Judges' remarks: @@ -34,7 +34,7 @@ This program was selected for the 1987 t-shirt collection. ## Author's remarks: -No comments were provided by the author. +No remarks were provided by the author. ## Copyright and CC BY-SA 4.0 License: diff --git a/1986/pawka/README.md b/1986/pawka/README.md index 425a7a708..247868801 100644 --- a/1986/pawka/README.md +++ b/1986/pawka/README.md @@ -7,14 +7,15 @@ San Diego, Ca ## To build: - - make all - +```sh +make all +``` ## Try: - ./pawka - +```sh +./pawka +``` ## Judges' remarks: @@ -24,7 +25,7 @@ is obfuscated, of all things! ## Author's remarks: -No comments were provided by the author. +No remarks were provided by the author. ## Copyright and CC BY-SA 4.0 License: diff --git a/1986/stein/README.md b/1986/stein/README.md index a515d6454..9112b5ff3 100644 --- a/1986/stein/README.md +++ b/1986/stein/README.md @@ -1,11 +1,12 @@ # Best one liner -Jan Stein +Jan Stein ## To build: - make all - +```sh +make all +``` ## Judges' remarks: @@ -16,9 +17,9 @@ the original file. Try the program with the following argument: - - ./stein ^N^N - +```sh +./stein ^N^N +``` (^N is ASCII control-N). One some machines, ^M^L is needed to get it to output cleanly. Your system may require another set of characters. @@ -26,7 +27,7 @@ In time, you will figure out what it does. :-) ## Author's remarks: -No comments were provided by the author. +No remarks were provided by the author. ## Copyright and CC BY-SA 4.0 License: diff --git a/1986/wall/README.md b/1986/wall/README.md index 32c722cd3..f083484ae 100644 --- a/1986/wall/README.md +++ b/1986/wall/README.md @@ -1,10 +1,7 @@ # The grand prize in most well-rounded in confusion Larry Wall -System Development Corporation -Santa Monica -California -US of A +US ## To build: @@ -17,7 +14,7 @@ this work with gcc (in particular the patch uses `strdup()` on two strings). Thank you Yusuke! [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed this so that it does not require `-traditional-cpp`. This took a fair bit of tinkering as this entry *is* strange. The original code is provided to allow one -to easily see how different C was in these days. See below for details. Thank +to easily see how different C was in those days. See below for details. Thank you Cody for your assistance! ## To use: @@ -49,14 +46,14 @@ This caused a number of System V C pre-preprocessors to gripe about a syntax error. This program is a masterpiece of obfuscation and humor. Larry Wall -(the hacker who gave us rn and patch) asks you to compile and consider +(the hacker who gave us `rn` and `patch`) asks you to compile and consider the warning message generated by the C compiler. Then execute the program and type characters into its standard input. You will see why the compiler documents the program. ## Author's remarks: -No comments were provided by the author. +No remarks were provided by the author. ## Copyright and CC BY-SA 4.0 License: diff --git a/1987/biggar/README.md b/1987/biggar/README.md index 42d51b877..09a7575d4 100644 --- a/1987/biggar/README.md +++ b/1987/biggar/README.md @@ -1,6 +1,6 @@ # Best Abuse of the Rules -Mark Biggar +Mark Biggar UNiSYS - System Development Group, Santa Monica 2525 Colorado AV MD 91-01 Santa Monica, CA @@ -8,27 +8,32 @@ Santa Monica, CA ## To build: - make all +```sh +make all +``` ## To run: - some_command | ./biggar | od -c +```sh +some_command | ./biggar | od -c +``` ## Try: - cat biggar.c | ./biggar | od -c - +```sh +cat biggar.c | ./biggar | od -c +``` ## Judges' remarks: By changing the compile line you can make this program do anything you -want. This is a very efficient way to transfer source, though it +want. This is a very efficient way to transfer source, though it increases the size of Makefiles. With only slight variations, this program can be set to many uses. Consider how easy it would be to release `Un*x` source in this form; -so what if the make files grow a little! :-) +so what if the Makefiles grow a little! :-) One vendor's lint got hung in an infinite loop over this entry! @@ -47,7 +52,7 @@ an infinite loop by this entry. ## Author's remarks: -No comments were provided by the author. +No remarks were provided by the author. ## Copyright and CC BY-SA 4.0 License: diff --git a/1987/heckbert/README.md b/1987/heckbert/README.md index ebbc4e06b..a26f9e0e1 100644 --- a/1987/heckbert/README.md +++ b/1987/heckbert/README.md @@ -5,8 +5,9 @@ Pixar ## To build: - make all - +```sh +make all +``` On System V systems, we had to compile with `-Dindex=strchr`. To compile on a 16 bit machine, change 300000 to 30000. @@ -15,35 +16,39 @@ To compile on a 16 bit machine, change 300000 to 30000. ## Try: - ./heckbert 40 < heckbert.c > ph.c; make ph - ./ph 21 < heckbert.c > bar.c; make bar - # or more generally fold some other file at a positive column: - ./ph col < file +```sh +./heckbert 40 < heckbert.c > ph.c; make ph +./ph 21 < heckbert.c > bar.c; make bar +# or more generally fold some other file at a positive column: +./ph col < file +``` Ask yourself what happens to `foo.md` if you try: - ./ph 40 < README.md > foo.md - +```sh +./ph 40 < README.md > foo.md +``` ## Judges' remarks: Folding at the wrong length may be equivalent to a "Spindle or Mutilate" operation. For example: - ./heckbert 40 < heckbert.c > ph.c ; make ph ; ./ph 20 < heckbert.c > bar.c ; make bar +```sh +./heckbert 40 < heckbert.c > ph.c ; make ph ; ./ph 20 < heckbert.c > bar.c ; make bar +``` Try not to [Fold, Spindle or Mutilate](https://repository.library.brown.edu/studio/item/bdr:788264/PDF/) files. :-) - -## Author's remarks: - -No comments were provided by the author. - The judges used this program to fold up very long lines which the BSD fold(1) was unable to process. This program has been added to the contest tool chest. +## Author's remarks: + +No remarks were provided by the author. + ## Copyright and CC BY-SA 4.0 License: This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved. diff --git a/1987/hines/README.md b/1987/hines/README.md index f1414594e..f4d8126fa 100644 --- a/1987/hines/README.md +++ b/1987/hines/README.md @@ -5,30 +5,38 @@ OnLine Computer Systems 4200 Farragut Street Hyattsville, MD 20781 -USA +US ## To build: - make all +```sh +make all +``` -## To run +## To run: - ./hines file.c +```sh +./hines file.c +``` ## Try: - ./hines hines.c +```sh +./hines hines.c +``` -### Alternate code +### Alternate code: -An alternate version of this entry is in `hines.alt.c`. With older compilers you +An alternate version of this entry is in [hines.alt.c](hines.alt.c). With older compilers you can try the alt version: - make alt +```sh +make alt +``` Use `hines.alt` as you would `hines` above. -## Judges' remarks +## Judges' remarks: This program was designed to maximize the bother function for structured programmers. This program takes goto statements to their @@ -41,7 +49,7 @@ See the Communications of the ACM, March 1987, Page 195-196. ## Author's remarks: -No comments were provided by the author. +No remarks were provided by the author. ## Copyright and CC BY-SA 4.0 License: diff --git a/1987/korn/README.md b/1987/korn/README.md index b4f036d9e..4c67c6dec 100644 --- a/1987/korn/README.md +++ b/1987/korn/README.md @@ -1,15 +1,17 @@ # Best One Liner -David Korn +David Korn AT&T Bell Labs -MH 3C-526B, AT&T Bell Labs -Murray Hill, NJ -07974 -USA +MH 3C-526B, AT&T Bell Labs +Murray Hill, NJ +07974 +US ## To build: - make all +```sh +make all +``` ## Judges' remarks: @@ -21,34 +23,44 @@ section right now and see if you are one of the few people who can. Several points are important to understand in this program: -1) What is the symbol 'unix' and what is its value in the program? - Clearly 'unix' is not a function, and since 'unix' is not declared - to be a data type (such as int, char, struct foo, enum, ...) - what must 'unix' be? +1. What is the symbol `unix` and what is its value in the program? Clearly +`unix` is not a function, and since `unix` is not declared to be a data type +(such as `int`, `char`, `struct foo`, `enum`, ...) what must `unix` be? -2) What is the value of the symbol "have"? (hint: the value is - NOT 4 characters, or 'h', or a string) Consider the fact that: +2. What is the value of the symbol `"have"`? (hint: the value is NOT 4 +characters, or `'h'`, or a string) Consider the fact that: - char *x; - defines a pointer to a character (i.e. an address), and that - the '=' assigns things is compatible types. Since: + char *x; + + + defines a pointer to a character (i.e. an address), and that the `=` assigns + things of compatible types. Since: + x = "have"; - is legal C, what type of value is "have"? + is legal C, what type of value is `"have"`? -3) Note that the following expressions yield the same value: +3. Note that the following expressions yield the same value: - x[3] *(x+3) *(3+x) - since addition is communitive. What can be said about the value: + x[3] *(x+3) *(3+x) - 3[x] + since addition is commutative. What can be said about the value: -David Korn's /bin/ksh provides us with a greatly improved version of + 3[x] + + ? + +David Korn's `/bin/ksh` provides us with a greatly improved version of the /bin/sh. The source for v7's /bin/sh greatly inspired this contest. +## Author's remarks: + +No remarks were provided by the author. + + ## Copyright and CC BY-SA 4.0 License: This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved. diff --git a/1987/lievaart/README.md b/1987/lievaart/README.md index d4626e0d6..f93561bb8 100644 --- a/1987/lievaart/README.md +++ b/1987/lievaart/README.md @@ -2,21 +2,24 @@ Roemer B. Lievaart VU Informatica -Churchilllaan 173-IV -Amsterdam, The Netherlands +Churchilllaan 173-IV +Amsterdam, The Netherlands ## To build: - make all +```sh +make all +``` NOTE: The original entry may be built with "make alt" if you have an old enough compiler. ## To run: - ./lievaart - # enter a level and start playing as described below - +```sh +./lievaart +# enter a level and start playing as described below +``` NOTE: if you enter invalid input the program will enter an infinite loop displaying a string like `"You:"` repeatedly. @@ -25,8 +28,10 @@ displaying a string like `"You:"` repeatedly. To see what it would have looked like without the size restrictions: - ./lievaart2 - # enter a level and start playing as described below +```sh +./lievaart2 +# enter a level and start playing as described below +``` ## Judges' remarks: @@ -34,19 +39,19 @@ To see what it would have looked like without the size restrictions: We believe that you too will be amazed at just how much power Mr. Lievaart packed into 1024 bytes! -This Plays the game of reversi (Othello)! Compile and run. It then +This Plays the game of Reversi (Othello)! Compile and run. It then asks for a playing level. Enter 0-10 (easy-hard). It then asks for your move. A move is a number within 11-88, or a 99 to pass. Illegal moves (except for an illegal pass) are rejected. Then the computer does its move (or a 0 to pass), until the board is full. It plays rather well, for such a small program! Lievaart had to leave out the -board printing routine, so you'll have to take a real game board to -play it. ... Also due to space-limitations (the rules for 1987 had a -limit of 1024 byes), Lievaart took out the passing-handler, which -makes its ending-game rather poor. But further it knows all the -rules, uses alpha-beta pruning, and it plays f.i. on mobility(!). -Most important: it can play a pretty good game of Reversi! +board printing routine, so you'll have to take a real game board to play it (or +see below). ... Also due to space-limitations (the rules for 1987 had a limit +of 1024 byes), Lievaart took out the passing-handler, which makes its +ending-game rather poor. But further it knows all the rules, uses alpha-beta +pruning, and it plays f.i. on mobility(!). Most important: it can play a pretty +good game of Reversi! The Author was kind enough to supply the fully functional version of the program. The file lievaart2.c contains what the program would have @@ -56,7 +61,7 @@ logic and displays the board after each move! ## Author's remarks: -No comments were provided by the author. +No remarks were provided by the author. ## Copyright and CC BY-SA 4.0 License: diff --git a/1987/wall/README.md b/1987/wall/README.md index 9aec8bd19..776dec55a 100644 --- a/1987/wall/README.md +++ b/1987/wall/README.md @@ -1,9 +1,7 @@ # Most Useful Obfuscation Larry Wall -Unisys - System Development Group Santa Monica -9132 Kester Ave -Panorama City, CA 91402 USA +US ## To build: @@ -23,35 +21,44 @@ make all ``` [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) made this safer by -using `fgets()` instead of `gets()`. This prevents a potentially alarming -warning at linking or runtime. +using `fgets()` instead of `gets()`. This prevents an annoying and potentially +alarming warning at compiling, linking or runtime. ## Try: - ./wall | bc | ./wall +```sh +./wall | bc | ./wall +``` and input the following: - x*x - c^2 - m*m +``` +x*x +c^2 +m*m - # can you figure out what this does? - 500 +# can you figure out what this does? +500 + +``` ### Also try: - ./wall | bc +```sh +./wall | bc - ./wall | cat +./wall | cat +``` and enter some input like: - x*x - 2^x - quit # for the cat version +``` +x*x +2^x +quit # for the cat version +``` ## Judges' remarks: @@ -64,12 +71,12 @@ be directly called. Even so, these pointers to functions are being used as an argument to signal. Can you determine why this is being done and how it is being exploited? -Some compilers complained about this file, so we changed: '=++I' to '= ++I'. +Some compilers complained about this file, so we changed: `=++I` to `= ++I`. ## Author's remarks: -No comments were provided by the author. +No remarks were provided by the author. ## Copyright and CC BY-SA 4.0 License: diff --git a/1987/westley/README.md b/1987/westley/README.md index 1d12594b5..729fc1ae2 100644 --- a/1987/westley/README.md +++ b/1987/westley/README.md @@ -1,34 +1,40 @@ # Best Layout - Brian Westley (aka Merlyn Leroy on usenet) - Starfire Consulting - 1121 Hamline Ave. N. #17 - St. Paul, MN - 55108 - USA - - http://www.westley.org +Brian Westley (aka Merlyn Leroy on usenet) +Starfire Consulting +1121 Hamline Ave. N. #17 +St. Paul, MN +55108 +US + ## To build: - make all +```sh +make all +``` [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed this for modern systems. The problem was 'assignment to cast is illegal, lvalue casts are not supported'. For the original file see below. Thank you Cody for your assistance! -## Alternate code: +## To run: + +```sh +./westley +``` + +### Alternate code: If you have an older compiler you can try compiling the original source code which is true symmetry: - make alt +```sh +make alt +``` - -## To run: - - ./westley +Use `westley.alt` as you would `westley` above. ## Judges' remarks: @@ -40,7 +46,11 @@ top of the program. Line by line symmetry performed better than any C beautifier. Think of if it as a C ink blot. :-) -NOTE: This entry requires a non-standard K&R C compiler to compile. + +## Author's remarks: + +No remarks were provided by the author. + ## Copyright and CC BY-SA 4.0 License: diff --git a/1988/applin/README.md b/1988/applin/README.md index 1545046c0..975486c2c 100644 --- a/1988/applin/README.md +++ b/1988/applin/README.md @@ -1,20 +1,24 @@ # Best of show - Jack Applin - Hewlett-Packard - 3404 E. Harmony Rd - Ft. Collins, CO - 80525 - USA +Jack Applin +Hewlett-Packard +3404 E. Harmony Rd +Ft. Collins, CO +80525 +US + ## To build: - make all - +```sh +make all +``` ## Try: - ./applin +```sh +./applin +``` ## Judges' remarks: @@ -22,19 +26,26 @@ This entry is by far the most unusual abuse of the C preprocessor that we have received thus far. Nearly all of the real work is done in the preprocessor! -When we compiled applin.c on an Amdahl 5890-300E, we found that it -spent over 75 minutes in the System V C preprocessor! Besides showing -that the standard System V cpp is slow, it showed that it contained a -memory usage problem. The applin.c only uses 29 different preprocessor -symbols (besides `stdio.h`) and yet the preprocessor ran out of space! +When we compiled [applin.c](applin.c) on an +[Amdahl](https://en.wikipedia.org/wiki/Amdahl_Corporation) 5890-300E, we found that it +spent over 75 minutes in the System V C preprocessor! Besides showing that the +standard System V cpp is slow, it showed that it contained a memory usage +problem. The [applin.c](applin.c) only uses 29 different preprocessor symbols +(besides `stdio.h`) and yet the preprocessor ran out of space! The GNU C preprocessor took less than 45 seconds to perform the 2nd pass on the Amdahl 5890-300E. But due to the ANSI-likeness of GNU cpp (v. 1-21), it was not able to cleanly substitute a symbol that began with a '#'. Clearly the GNU C preprocessor is faster. -A smaller version of applin.c can be found in zsmall.c. Your machine -may have an easier time with this program. See the Makefile for details. +A smaller version of [applin.c](applin.c) can be found in [zsmall.c](zsmall.c). +Your machine may have an easier time with this program. See the Makefile for +details. + +## Author's remarks: + +No remarks were provided by the author. + ## Copyright and CC BY-SA 4.0 License: diff --git a/1988/dale/README.md b/1988/dale/README.md index 2031a5a16..6bf4f0222 100644 --- a/1988/dale/README.md +++ b/1988/dale/README.md @@ -1,11 +1,11 @@ ## Best abuse of system calls -Paul Dale -University of Queensland -Computer Science Dept -Dept of Computer Science -Uni of Qld, 4067 -Australia +Paul Dale +University of Queensland +Computer Science Dept +Dept of Computer Science +Uni of Qld, 4067 +Australia ## To build: @@ -56,9 +56,10 @@ Thank you Cody for your assistance! ## Try: - - ./dale hello world - ./dale these files are in this directory: * +```sh +./dale hello world +./dale these files are in this directory: * +``` NOTE: in linux it might happen that core dumps are created when running this entry even though it works fine. @@ -71,6 +72,11 @@ system calls. NOTE: This program assumes the ASCII character set is being used. +## Author's remarks: + +No remarks were provided by the author. + + ## Copyright and CC BY-SA 4.0 License: This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved. diff --git a/1988/isaak/README.md b/1988/isaak/README.md index 44978b4f7..251133c20 100644 --- a/1988/isaak/README.md +++ b/1988/isaak/README.md @@ -1,19 +1,23 @@ # Best visuals - Mark Isaak - Imagen Corporation - 2650 San Tomas Expy. - Santa Clara, CA - 95052-8101 - USA +Mark Isaak +Imagen Corporation +2650 San Tomas Expy. +Santa Clara, CA +95052-8101 +US ## To build: - make all +```sh +make all +``` ## To run: - ./isaak +```sh +./isaak +``` [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed this to work for modern systems. The problem was that the important function, a redefinition of @@ -25,7 +29,9 @@ alternative version. Thank you Cody for your assistance! The original version of this code is in [isaak.alt.c](isaak.alt.c). The original entry starts with the line: +```c main(){}; +``` This works on some systems. Why? Note that `#include ` is given on the last line. Why is this needed? Note the unusual calls to sprintf. @@ -50,14 +56,21 @@ due to the fact that BSD style systems have an sprintf() that returns a `char *` Due to the above problems, we placed the output of this program in the file: isaak.encode. To read this file do: - uudecode < isaak.encode - cat isaak.output +```sh +uudecode < isaak.encode +cat isaak.output +``` But since Cody fixed it this is not strictly necessary. See the [isaak.alt.c](isaak.alt.c) for the original source. FYI: We are likely to be more strict about portability in the future. +## Author's remarks: + +No remarks were provided by the author. + + ## Copyright and CC BY-SA 4.0 License: This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved. diff --git a/1988/litmaath/README.md b/1988/litmaath/README.md index d8ec7aba6..18f04cf50 100644 --- a/1988/litmaath/README.md +++ b/1988/litmaath/README.md @@ -1,15 +1,17 @@ ## Best small program - Maarten Litmaath - Free University (VU) Amsterdam - Department of computer science - Uilenstede 72 - 1183 AK Amstelveen - The Netherlands +Maarten Litmaath +Free University (VU) Amsterdam +Department of computer science +Uilenstede 72 +1183 AK Amstelveen +The Netherlands ## Try: - ./litmaath eschew obfuscation +```sh +./litmaath eschew obfuscation +``` ## Judges' remarks: @@ -17,9 +19,10 @@ Note the unusual structure: - while () - ; - +```c +while () + ; +``` Did you notice that the body is empty? @@ -30,15 +33,22 @@ could make the body of the 'while' loop an 'fprintf' with interesting variables like: - fprintf(stderr, - "argv=%lo *argv=%lo **argv=%c argv[1]=%lo *argv[1]=%c argc=%d\n", - (long) argv, (long) *argv, *argv && **argv ? **argv : '@', - (long) argv[1], argv[1] && *argv[1] ? *argv[1] : '@', argc); +```c +fprintf(stderr, + "argv=%lo *argv=%lo **argv=%c argv[1]=%lo *argv[1]=%c argc=%d\n", + (long) argv, (long) *argv, *argv && **argv ? **argv : '@', + (long) argv[1], argv[1] && *argv[1] ? *argv[1] : '@', argc); +``` Furthermore, it's interesting to note that only two variables are used to achieve everything. +## Author's remarks: + +No remarks were provided by the author. + + ## Copyright and CC BY-SA 4.0 License: This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved. diff --git a/1988/phillipps/README.md b/1988/phillipps/README.md index 82de57d19..f8eca64ad 100644 --- a/1988/phillipps/README.md +++ b/1988/phillipps/README.md @@ -1,17 +1,18 @@ ## Least likely to compile successfully - Ian Phillipps - Cambridge Consultants Ltd - Science Park - Milton Road - Cambridge CB4 4DW - England +Ian Phillipps +Cambridge Consultants Ltd +Science Park +Milton Road +Cambridge CB4 4DW +England ## To build: - - make all +```sh +make all +``` [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed this for modern @@ -23,7 +24,7 @@ be `char **` :-) ) with the correct args it now works. Thank you Cody for your assistance! -## Judges' remarks +## Judges' remarks: Compile and run without parameters. @@ -33,6 +34,11 @@ and thus represents a new departure in text compression standards. The judges thought that this program looked like what you would get by pounding on the keys of an old typewriter at random. +## Author's remarks: + +No remarks were provided by the author. + + ## Copyright and CC BY-SA 4.0 License: This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved. diff --git a/1988/reddy/README.md b/1988/reddy/README.md index 64bf1ead6..f7beabb92 100644 --- a/1988/reddy/README.md +++ b/1988/reddy/README.md @@ -1,29 +1,38 @@ ## Most useful Obfuscated C program - Amperif Corporation - 9232 Eton Avenue - Chatsworth, CA - 91311 - U.S.A. +Amperif Corporation +9232 Eton Avenue +Chatsworth, CA +91311 +U.S.A. ## To build: - make all +```sh +make all +``` ## Try: - ./reddy - char *(*(fun[16])(); +```sh +./reddy +char *(*(fun[16])(); +``` -## Judges' remarks +## Judges' remarks: This is a somewhat restricted version of a useful program that has been posted to Usenet. What is unusual is what it is able to do so much in such little space. +## Author's remarks: + +No remarks were provided by the author. + + ## Copyright and CC BY-SA 4.0 License: This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved. diff --git a/1988/robison/README.md b/1988/robison/README.md index 49600c6a2..488b7c8d6 100644 --- a/1988/robison/README.md +++ b/1988/robison/README.md @@ -1,45 +1,57 @@ ## Best abuse of C constructs - Arch D. Robison - University of Illinois at Urbana-Champaign - 1304 W. Springfield Ave. - Urbana IL - 61801 - USA +Arch D. Robison +University of Illinois at Urbana-Champaign +1304 W. Springfield Ave. +Urbana IL +61801 +US ## To build: - make all +```sh +make all +``` ## Try: - ./robison 80 10 - ./robison 40 16 +```sh +./robison 80 10 +./robison 40 16 +``` The first and second parameters are optional. You might also try: - ./robison 80 2 <--- can you find the bug? - ./robison 80 -246 +```sh +./robison 80 2 # <--- can you find the bug? +./robison 80 -246 +``` -The author says: - -> This program shows that C has many unnecessary constructs, in fact -> only "while","--", and ">=" are required. (The two assignments at -> the beginning could be avoided if "atoi" was rewritten with this -> new paradigm.) Note that the lack of both the controversial "goto" -> and assignment statements makes the meaning crystal clear. The current -> ANSI committee should look into this practical simplification of C. +## Judges' remarks: The following might make an interesting benchmark: - ./robison 100 +```sh +./robison 100 + +``` [Amdahl 5890-300E with System V cc: 8.40 seconds] We suggest that you C pre-process and perhaps C-beautify this program. -All is not what it may appear to be in this program. Why does a whi1e +All is not what it may appear to be in this program. Why does a `whi1e` not take a while to execute? + +## Author's remarks: + +This program shows that C has many unnecessary constructs, in fact +only "while","--", and ">=" are required. (The two assignments at +the beginning could be avoided if "atoi" was rewritten with this +new paradigm.) Note that the lack of both the controversial "goto" +and assignment statements makes the meaning crystal clear. The current +ANSI committee should look into this practical simplification of C. + ## Copyright and CC BY-SA 4.0 License: This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved. diff --git a/1988/spinellis/README.md b/1988/spinellis/README.md index 4b9be63bf..18b93c7e4 100644 --- a/1988/spinellis/README.md +++ b/1988/spinellis/README.md @@ -8,8 +8,9 @@ Greece ## To build: - - make all +```sh +make all +``` and then type a C program into followed by EOF (usually `^D`, ctrl-d). @@ -19,23 +20,25 @@ Thank you Cody for your assistance! ## Try: - make clobber all - main() - { - printf("Hello world\n"); - } - ^D - ./spinellis +```sh +make clobber all +main() +{ + printf("Hello world\n"); +} +^D +./spinellis - make clobber all - int main() - { - int i; - for (i = 0; i < 5; ++i) - printf("%d\n", i); - } - ^D - ./spinellis +make clobber all +int main() +{ + int i; + for (i = 0; i < 5; ++i) + printf("%d\n", i); +} +^D +./spinellis +``` NOTE: you need to make clobber first for this entry to work right. @@ -43,15 +46,17 @@ NOTE: you need to make clobber first for this entry to work right. For clang try the alt code like: - make clobber alt - #include - main() - { - puts("Hello world\n"); - } - ^D - ./spinellis +```sh +make clobber alt +#include +main() +{ + puts("Hello world\n"); +} +^D +./spinellis +``` NOTE: you need to make clobber first for this entry to work right. diff --git a/1988/westley/.gitignore b/1988/westley/.gitignore index 2a0c890f9..0c08f64e6 100644 --- a/1988/westley/.gitignore +++ b/1988/westley/.gitignore @@ -1 +1,2 @@ westley +westley.alt diff --git a/1988/westley/Makefile b/1988/westley/Makefile index 440787728..c4a7ed1ad 100644 --- a/1988/westley/Makefile +++ b/1988/westley/Makefile @@ -112,8 +112,8 @@ OBJ= ${PROG}.o DATA= TARGET= ${PROG} # -ALT_OBJ= -ALT_TARGET= +ALT_OBJ= ${PROG}.alt.o +ALT_TARGET= ${PROG}.alt ################# diff --git a/1988/westley/README.md b/1988/westley/README.md index 42771de33..1a32e73bc 100644 --- a/1988/westley/README.md +++ b/1988/westley/README.md @@ -1,40 +1,71 @@ ## Best layout - Merlyn LeRoy (Brian Westley) - Rosemount, Inc. - 1121 Hamline Ave. N. #17 - St. Paul, MN - 55108 - U.S.A. +Merlyn LeRoy (Brian Westley) +Rosemount, Inc. +1121 Hamline Ave. N. #17 +St. Paul, MN +55108 +U.S.A. + - http://www.westley.org +## To build: + +```sh +make all +``` + +Misha Dynin provided a fix for [westley.c](westley.c) so that it may compile on +both K&R and more modern C compilers. Thank you Misha! The original code, used +for entertainment and educational value, is in [westley.alt.c](westley.alt.c), +described below. ## Try: - make all - ./westley +```sh +./westley +``` - -## Judges' remarks +## Judges' remarks: Your compiler must parse - #define _ -a - -_ +```c +#define _ -a +-_ +``` -as "--a" and not "-(-a)" or some other tokenized form. Some strictly +as `--a` and not `-(-a)` or some other tokenized form. Some strictly conforming ANSI C Preprocessors may object to this: for such compilers, you can elide the non-standard token-pasting requirement by changing the #define line to: - #define _ F-->00||F-OO--; +```c +#define _ F-->00||F-OO--; +``` You might enjoy looking at the output of: - cc -E westley.c +```sh +cc -E westley.c +``` + +### Alternate code: + +To see if your compiler has the problem described above try: + +```sh +make alt +./westley.alt +``` + +Does it show the same output as `westley`? + + +## Author's remarks: + +No remarks were provided by the author. + -Misha Dynin provided a fix for westley.c so that it may compile on -both K&R and more modern C compilers. ## Copyright and CC BY-SA 4.0 License: diff --git a/1988/westley/westley.alt.c b/1988/westley/westley.alt.c new file mode 100644 index 000000000..8398d5f7a --- /dev/null +++ b/1988/westley/westley.alt.c @@ -0,0 +1,20 @@ +#define _ -F<00||--F-OO--; +int F=00,OO=00;main(){F_OO();printf("%1.3f\n",4.*-F/OO/OO);}F_OO() +{ + _-_-_-_ + _-_-_-_-_-_-_-_-_ + _-_-_-_-_-_-_-_-_-_-_-_ + _-_-_-_-_-_-_-_-_-_-_-_-_-_ + _-_-_-_-_-_-_-_-_-_-_-_-_-_-_ + _-_-_-_-_-_-_-_-_-_-_-_-_-_-_ +_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ +_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ +_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ +_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ + _-_-_-_-_-_-_-_-_-_-_-_-_-_-_ + _-_-_-_-_-_-_-_-_-_-_-_-_-_-_ + _-_-_-_-_-_-_-_-_-_-_-_-_-_ + _-_-_-_-_-_-_-_-_-_-_-_ + _-_-_-_-_-_-_-_ + _-_-_-_ +} diff --git a/1989/fubar/README.md b/1989/fubar/README.md index 3442e0791..9c13c3d34 100644 --- a/1989/fubar/README.md +++ b/1989/fubar/README.md @@ -1,40 +1,47 @@ # Best self-modifying program - Jay Vosburgh - Sequent Computer Systems, Inc - 15450 SW Koll Parkway - Beaverton, OR - 97006 - USA +Jay Vosburgh +Sequent Computer Systems, Inc +15450 SW Koll Parkway +Beaverton, OR +97006 +US ## To build: - make all +```sh +make all +``` [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) got this to work with modern systems. Thank you Cody for your assistance! -## To run +## To run: - ./fubar number> +```sh +./fubar +``` ## Try: - ./fubar 2 +```sh +./fubar 2 +``` -## Judges' remarks +## Judges' remarks: Run this with a single digit argument (or wait a long time). The blank line at the beginning of the source is mandatory. Do you know why? -NOTE: don't try running `ouroboros.c` directly with an arg as it'll turn into an -infinite loop. The same will happen with larger numbers. +NOTE: don't try running [ouroboros.c](ouroboros.c) (note that it's executable) +directly with an arg as it'll turn into an infinite loop. The same will happen +with larger numbers. -## Author's remarks +## Author's remarks: In a nutshell, this is probably the slowest and most obnoxious factorial program ever written. Unfortunately, @@ -46,7 +53,7 @@ The shell script compiles itself, and then executes the resulting binary, giving the source as input. The program works by successively modifying #define lines each pass through. -Both "indent" and "cb" will damage the program, "indent" +Both `indent` and `cb` will damage the program, `indent` much more so. ## Copyright and CC BY-SA 4.0 License: diff --git a/1989/jar.1/README.md b/1989/jar.1/README.md index 846005637..587d958ec 100644 --- a/1989/jar.1/README.md +++ b/1989/jar.1/README.md @@ -1,34 +1,40 @@ # Strangest abuse of the rules - Jari Arkko - Laboratory of Information Processing Science - Helsinki University of Technology - Otakaari 1 - 02150 Espoo - Finland +Jari Arkko +Laboratory of Information Processing Science +Helsinki University of Technology +Otakaari 1 +02150 Espoo +Finland ## To build and run: - make clobber all +```sh +make clobber all +``` -## Judges notes: +## Judges' remarks: On many systems the compiler will not allow you to send the object file to /dev/tty. The author suggested: - cc -c -o /dev/tty jar.1.c +```sh +cc -c -o /dev/tty jar.1.c +``` On systems that have symbolic links, we suggest: - ln -s /dev/tty jar.1.o - cc -c jar.1.c +```sh +ln -s /dev/tty jar.1.o +cc -c jar.1.c +``` As a last resort the scripts provided simply cat the .o file to the terminal. Abuse of the rules winners usually result in a change of the rules. Starting in 1990, compiling entries must result an regular file which can be executed. -## Selected notes from the author: +## Author's remarks: This program is (supposedly) the smallest C program able to print "Hello world.". The compilation itself produces the desired printout and the program diff --git a/1989/jar.2/README.md b/1989/jar.2/README.md index a426ddf25..255b5acee 100644 --- a/1989/jar.2/README.md +++ b/1989/jar.2/README.md @@ -1,33 +1,41 @@ ## Best of show - Jari Arkko, Ora Lassila, Esko Nuutila - Laboratory of Information Processing Science - Helsinki University of Technology - Otakaari 1 - 02150 Espoo - Finland +Jari Arkko, Ora Lassila, Esko Nuutila +Laboratory of Information Processing Science +Helsinki University of Technology +Otakaari 1 +02150 Espoo +Finland ## To build: - make all +```sh +make all +``` [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed this to work with modern compilers. Modern compilers do not allow code like: - #define D define - #define a include +```c +#define D define +#define a include - #D foo bar - #a +#D foo bar +#a +``` + +He notes that there _is_ a way to get it (or something close to it) to work. Do +you know how? Thank you Cody for your assistance! ## To run: - - ./jar.2 - [enter some lisp] +```sh +./jar.2 +[enter some lisp] +``` NOTE: this entry will likely segfault on invalid input. @@ -40,15 +48,27 @@ all this functionality in such a small, densely packed program, is impressive enough to win the Best of show award. -## Selected notes from the author: +## Author's remarks: This program implements a Lisp interpreter in 1465 bytes of source. Some sophisticated features supported, eg. functionals and recursion. The special-forms/functions/variables implemented are: - + - * < () - car cdr cons defun equal - function if lambda quote t +- \+ +- \- +- \* +- \< +- () +- car +- cdr +- cons +- defun +- equal +- function +- if +- lambda +- quote +- t Below are sample lisp expressions you might choose to try as input. The program implements a conventional lisp listener, i.e. you type in @@ -56,6 +76,7 @@ lisp expressions (followed by CR), the program evaluates them and prints out the return values. End execution by typing an end-of-file character. +```lisp (+ 2.5 3.1) (defun fib (n) (if (< n 2) @@ -74,6 +95,7 @@ character. (cons (quote (f)) ()) (car (quote (a b c))) (cdr (cdr (quote (g h i)))) +``` Please do not leave any whitespace before the first parenthesis when diff --git a/1989/ovdluhe/.gitignore b/1989/ovdluhe/.gitignore index 14b8483be..e3366e267 100644 --- a/1989/ovdluhe/.gitignore +++ b/1989/ovdluhe/.gitignore @@ -1 +1,2 @@ ovdluhe +ovdluhe.alt diff --git a/1989/ovdluhe/Makefile b/1989/ovdluhe/Makefile index 597aede89..34f9f9ef7 100644 --- a/1989/ovdluhe/Makefile +++ b/1989/ovdluhe/Makefile @@ -115,8 +115,8 @@ OBJ= ${PROG}.o DATA= TARGET= ${PROG} # -ALT_OBJ= -ALT_TARGET= +ALT_OBJ= ${PROG}.alt.o +ALT_TARGET= ${PROG}.alt ################# @@ -138,6 +138,9 @@ ${PROG}: ${PROG}.c alt: data ${ALT_TARGET} @${TRUE} +${PROG}.alt: ${PROG}.alt.c + ${CC} ${CFLAGS} $< -o $@ ${LIBS} + # data files # data: ${DATA} diff --git a/1989/ovdluhe/README.md b/1989/ovdluhe/README.md index 2c0dbb685..3182ad944 100644 --- a/1989/ovdluhe/README.md +++ b/1989/ovdluhe/README.md @@ -1,14 +1,16 @@ ## Most humorous output - Oskar von der Luehe - Institut fuer Astronomie - ETH - Zentrum - 8092 Zuerich - Switzerland +Oskar von der Luehe +Institut fuer Astronomie +ETH - Zentrum +8092 Zuerich +Switzerland ## To build: - make all +```sh +make all +``` To get this to compile with a modern CPP, we had to replace `#D` with `#define`. @@ -16,19 +18,34 @@ To get this to compile with a modern CPP, we had to replace `#D` with `#define`. Run the program this way: - ./ovdluhe < textfile +```sh +./ovdluhe < textfile +``` The program stops when it reaches the end of the template buffer by chance or is killed. ## Try: - ./ovdluhe < ./ovdluhe.c - ./ovdluhe < ./ovdluhe.c +```sh +./ovdluhe < ./ovdluhe.c +./ovdluhe < ./ovdluhe.c - ./ovdluhe < README.md - ./ovdluhe < README.md +./ovdluhe < README.md +./ovdluhe < README.md +``` +### Alternate code: + +The author suggested that one varies the definition of `P` from 2 through 10. As +it's a `#define` it's easy to set up which [Cody Boone +Ferguson](/winners.html#Cody_Boone_Ferguson) did for us. To use try: + +```sh +make CFLAGS="-DP=9" clobber alt +``` + +Use `ovdluhe.alt` as you would `ovdluhe`. ## Judges' remarks: @@ -38,7 +55,7 @@ recommended. You will get different output each time you run it. -## Selected notes from the author: +## Author's remarks: This program implements an "Eddington ape" - it generates random text from a supplied template. The template text file diff --git a/1989/ovdluhe/ovdluhe.alt.c b/1989/ovdluhe/ovdluhe.alt.c new file mode 100644 index 000000000..9aad1945e --- /dev/null +++ b/1989/ovdluhe/ovdluhe.alt.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include +typedef char ape; +#define EA register +#define EP unsigned +#define A 1 +#define AP (A<>A) +#define APE {EA EP ape,ea=AE;while(ea--) e[ea]=E;} +PA(); +;ape a[PE+A],ap,*ae,p[P+A],e[AE]; +main(){ape pe,*ep=a;srand((EP)time((long)E)); +while(((*(ep++)=getchar())!=-A)&&((ep-a) - drop - p - pause - q - quit +- j - left +- k - rotate +- l - right +- space - drop +- p - pause +- q - quit Specifying "cmd_string" allows one to re-define the commands. The pause command pauses the game, clears the screen and -prints the current score. To un-pause, type the pause +prints the current score. To resume, type the pause character again, which by default is "p". As was stated last year, we are likely to be more strict about portability in the future. [ We mean it this time :-) ] -## Author's remarks +## Author's remarks: This program plays the familiar game of `TETRIS' with the following features: @@ -131,6 +141,7 @@ at the start and -raw at the end. This further reduces the size of the program, but has the possible disadvantage that the program can only by stopped by 'q' or by the `kill -9' command. +```c long h[4];t(){h[3]-=h[3]/3000;setitimer(0,h,0);}c,d,l,v[]={(int)t,0,2},w,s,I,K =0,i=276,j,k,q[276],Q[276],*n=q,*m,x=17,f[]={7,-13,-12,1,8,-11,-12,-1,9,-1,1, 12,3,-13,-12,-1,12,-1,11,1,15,-1,13,1,18,-1,1,2,0,-12,-1,11,1,-12,1,13,10,-12, @@ -150,6 +161,7 @@ can only by stopped by 'q' or by the `kill -9' command. 0);while(getchar()-a[4]);puts("\033[H\033[J\033[7m");sigsetmask(s);}}d=popen( "stty -cbreak echo stop \023;sort -mnr -o HI - HI;cat HI","w");fprintf(d, "%4d from level %1d by %s\n",w,l,getlogin());pclose(d);} +``` ## Copyright and CC BY-SA 4.0 License: diff --git a/1989/vanb/README.md b/1989/vanb/README.md index 114b70095..9bcfb961e 100644 --- a/1989/vanb/README.md +++ b/1989/vanb/README.md @@ -1,21 +1,25 @@ ## Best one liner - David Van Brackle - Department of Computer Science - University of Central Florida - Orlando, Florida - 32816 - USA +David Van Brackle +Department of Computer Science +University of Central Florida +Orlando, Florida +32816 +US ## To build: - make all +```sh +make all +``` ## Try: - ./vanb the rug gary lent - ./vanb unix is better than os/2 +```sh +./vanb the rug gary lent +./vanb unix is better than os/2 +``` ## Judges' remarks: @@ -25,7 +29,7 @@ element on each line, followed by a line of ten dashes. -## Selected notes from the author: +## Author's remarks: The program has the following charming and possibly non-portable features: diff --git a/1989/westley/README.md b/1989/westley/README.md index 7d7323d5b..fef7065d0 100644 --- a/1989/westley/README.md +++ b/1989/westley/README.md @@ -1,23 +1,24 @@ # Most algorithms in one program - Merlyn LeRoy (Brian Westley) - Starfire Consulting - 1026 Blair Ave. - St. Paul, MN - 55104 - USA - - http://www.westley.org +Merlyn LeRoy (Brian Westley) +Starfire Consulting +1026 Blair Ave. +St. Paul, MN +55104 +US + ## To build: - make all +```sh +make all +``` [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) was able to get this to partially work with clang; clang requires that the second, third and fourth args to main() be `char **`. Only `westley.c` and `ver0.c` (see below) will -compile with clang. It's possible to get ver1.c to compile too but this causes +compile with clang. It's possible to get `ver1.c` to compile too but this causes problems with generating the output of the remaining files so we have opted, at least for now, to not do that, as it does not have to output just source code. He notes that the original source code sometimes segfaults with `ver2` which @@ -28,31 +29,32 @@ Thank you Cody for your help! ## Try: - - ./westley < westley.c > ver0.c - ./westley 1 < westley.c > ver1.c - ./westley 1 2 < westley.c > ver2.c - ./westley 1 2 3 < westley.c > ver3.c +```sh +./westley < westley.c > ver0.c +./westley 1 < westley.c > ver1.c +./westley 1 2 < westley.c > ver2.c +./westley 1 2 3 < westley.c > ver3.c +``` Try compiling and running the 4 resulting programs. To compile try: - - make ver0 - make ver1 - make ver2 - make ver3 +```sh +make ver0 +make ver1 +make ver2 +make ver3 +``` - -## Judges notes: +## Judges' remarks: There is a secret way to get ONE of the versions to print out "Hello, world!\n". Can you find how to do it? -## Selected notes from the author: +## Author's remarks: This is a filter. If it is run with no arguments, it copies stdin to stdout. With one argument, it ROT13's stdin to @@ -63,42 +65,44 @@ Also requires two's complement (I think). The source code will run if ROT13'ed and/or reversed, using a different algorithm for each version (hereafter referred to as -ver0 (original), ver1 (ROT13), ver2 (reversed), and ver3 +`ver0` (original), `ver1` (ROT13), `ver2` (reversed), and `ver3` (ROT13 and reversed)). When compiling these versions, one needs to define 'trgpune' in the compile line (which the Makefile now has). Example: - cc -Dtrgpune=putchar ver3.c -o ver3 +```sh +cc -Dtrgpune=putchar ver3.c -o ver3 +``` -"trgpune" is the ROT13 of getchar(), so getchar() and putchar() +`trgpune` is the ROT13 of `getchar()`, so `getchar()` and `putchar()` are exchanged in the ROT13 counterpart. It is easy to see that -this is unavoidable. I must have a #define for a library +this is unavoidable. I must have a `#define` for a library function; otherwise I would have an unidentified extern for the ROT13 version. If I then define this function, it won't link in the library version for the ORIGINAL code, since my definition will supersede the library function. Hence, the -compiler option gives me putchar(), and allows me to use -getchar(). I pass a dummy argument to getchar() to eliminate +compiler option gives me `putchar()`, and allows me to use +`getchar()`. I pass a dummy argument to `getchar()` to eliminate "variable number of args" from lint (unless it checks against the library). Otherwise, all versions lint reasonably (main returns random value & constant in conditional context [when I check for ROT13 version] is all it complains about). -ver0 and ver1 use a range check and a calculation to do ROT13, -while ver2 and ver3 use table lookup. All versions contain -main() and it's ROT13 fn, znva(). ver0/ver1 [ver2/ver3] are +`ver0` and `ver1` use a range check and a calculation to do ROT13, +while `ver2` and `ver3` use table lookup. All versions contain +`main()` and it's ROT13 fn, `znva()`. `ver0`/`ver1` [`ver2`/`ver3`] are (of course) syntactically identical, since the syntax is in the non-alphabetic characters. However, since one program starts -at main() while it's ROT13 counterpart starts at znva(), znva() -calls main (znva() is also used for output). +at `main()` while it's ROT13 counterpart starts at `znva()`, `znva()` +calls main (`znva()` is also used for output). All versions use recursion to work. If the program is NOT reversing it's output, it prints out the (possibly ROT13'd) character before recursing, otherwise it prints it out afterward (or doesn't recurse at all when EOF is reached). -Since most of this code is identical, it is put into znva() and -called with a first parameter of 0 as a flag (as "main()", it's +Since most of this code is identical, it is put into `znva()` and +called with a first parameter of 0 as a flag (as `main()`, it's first argument (argc) must be at least one). I can't use any flow control. If I used if(), I would have a @@ -106,45 +110,62 @@ function vs() to define in the ROT13 version. But a function called vs() turns into a function called if() in the original, so it can't be done. Therefore, I do: - expr1 && expr2 && (expr3=etc); +```c +expr1 && expr2 && (expr3=etc); +``` which is the same as: - if (expr1 && expr2) expr3=etc; +```c +if (expr1 && expr2) expr3=etc; +``` A/UX on the Macintosh doesn't get this right; it evaluates ALL expressions if they aren't in an assignment or conditional statement. This might warrant a warning, since other compilers may do this. I found MANY compilers botched: - expr1 && (expr2,expr3); +```c +expr1 && (expr2,expr3); +``` -expr2 was OFTEN evaluated even if expr1 was false. I removed +`expr2` was OFTEN evaluated even if `expr1` was false. I removed such statements to make it more portable. The variable names are worth noting: - 'irk' and 'vex' are ROT13 pairs and are synonyms. - 'Near' and 'Arne' are ROT13 pairs and are anagrams. - 'NOON' and 'ABBA' are ROT13 pairs and are palindromes. - 'tang' and 'gnat' are both ROT13 and palindrome pairs! +-- + +'irk' and 'vex' are ROT13 pairs and are synonyms. + +'Near' and 'Arne' are ROT13 pairs and are anagrams. + +'NOON' and 'ABBA' are ROT13 pairs and are palindromes. + +'tang' and 'gnat' are both ROT13 and palindrome pairs! + +-- Normally (!), a reversible C program is done thus: - /**/ forward code /*/ edoc drawkcab /**/ +```c +/**/ forward code /*/ edoc drawkcab /**/ +``` If your compiler nests comments, it will get this wrong. However, I have made some bits of the code palindromic, (or different, but reversible) so it is more like: - /**/forward/*//**/ palindromic /**//*/drawkcab/**/ +```c +/**/forward/*//**/ palindromic /**//*/drawkcab/**/ +``` The code can therefore be interlaced. There are eight such palindromic bits. You can find them within the `/*//**/ /**//*/` pairs. -The body of the code of ver0 and ver1 is a large lumpy 'K' (for -Kernighan); the code of ver2 and ver3 is a flat-topped and +The body of the code of `ver0` and `ver1` is a large lumpy 'K' (for +Kernighan); the code of `ver2` and `ver3` is a flat-topped and lumpier 'R' (for Ritchie). Judicious use of spaces and tabs helped here. It barely fits on an 80x24 screen. Squint. Note that the code must start with a blank line, or the reversed version diff --git a/1990/baruch/.gitignore b/1990/baruch/.gitignore index 20e5ca7fd..c31461210 100644 --- a/1990/baruch/.gitignore +++ b/1990/baruch/.gitignore @@ -1 +1,2 @@ baruch +baruch.alt diff --git a/1990/baruch/baruch.alt.c b/1990/baruch/baruch.alt.c new file mode 100644 index 000000000..8b7f770e9 --- /dev/null +++ b/1990/baruch/baruch.alt.c @@ -0,0 +1,6 @@ +int v,i,j,k,l,s,a[99]; +int main(void) +{ + for(scanf("%d",&s);*a-s;v=a[j*=v]-a[i],k=i=s*k&&++a[--i]) + ;puts(""); +} diff --git a/1990/cmills/README.md b/1990/cmills/README.md index 37b9fdb49..7c9b8f5f4 100644 --- a/1990/cmills/README.md +++ b/1990/cmills/README.md @@ -4,7 +4,7 @@ Chris Mills Wyse Technology 3471 N. 1st St. San Jose CA 95134 -USA +US ## To build: @@ -12,7 +12,7 @@ USA make all ``` -## To run +## To run: ```sh ./cmills [starting_cash] @@ -23,8 +23,9 @@ work in modern systems (it resulted in a bus error otherwise). Thank you Yusuke for your assistance! [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) made this safer by -using `fgets()` instead of `gets()`. This avoids a potentially alarming warning -at compiling and/or linking and/or runtime. Thank you Cody for your assistance! +using `fgets()` instead of `gets()`. This avoids an annoying and potentially +alarming warning at compiling and/or linking and/or runtime that in some cases +is interspersed with the program's output. Thank you Cody for your assistance! For the original code see the [1992 archive](/archive/archive-1990.tar.bz2). diff --git a/1990/dds/README.md b/1990/dds/README.md index 9392b5778..a18fc84c6 100644 --- a/1990/dds/README.md +++ b/1990/dds/README.md @@ -5,11 +5,13 @@ Imperial College, University of London Myrsinis 1 GR-145 62 Kifissia Greece - + ## To build: - make all +```sh +make all +``` [Yusuke Endoh](/winners.html#Yusuke_Endoh) fixed this for modern systems. Thank @@ -17,10 +19,10 @@ you Yusuke! [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) removed the erroneous prototype to `fopen()` and made this use `fgets()` instead of `gets()` to make -it safer and to prevent a potentially alarming warning at compiling and/or -linking and/or runtime. Thank you Cody for your assistance! +it safer and to prevent an annoying and potentially alarming warning at +compiling and/or linking and/or runtime. Thank you Cody for your assistance! -## To run +## To run: ```sh ./dds diff --git a/1990/dg/README.md b/1990/dg/README.md index 32dd59b67..f48d6d0c7 100644 --- a/1990/dg/README.md +++ b/1990/dg/README.md @@ -4,7 +4,7 @@ David Goodenough anonymous organization 541 Commonwealth Ave Newton, MA 02159 -USA +US ## To build: diff --git a/1990/jaw/README.md b/1990/jaw/README.md index 59e831414..b934acb95 100644 --- a/1990/jaw/README.md +++ b/1990/jaw/README.md @@ -5,19 +5,19 @@ Research Institute for Advanced Computer Science MS 230-5 NASA Ames Research Center Moffett Field, CA 94131 -USA +US Karl F. Fox Morning Star Technologies, Inc. 1760 Zollinger Road Columbus, OH 43221 -USA +US Paul Eggert Twin Sun Inc. 360 N. Sepulveda Blvd. #2055 El Segundo, CA 90245 -USA +US ## To build: @@ -27,7 +27,7 @@ make all [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed the script to work properly in modern environments (to do with PATH not having '.' in it). He -notes that with an invocation in the try section below you will with macOS get +notes that with an invocation in the try section below will with macOS show what appears to be an error message but is actually okay. He gives more information in the [bugs.md](/bugs.md) file. Thank you Cody for the help and notes! @@ -136,7 +136,7 @@ environment. ---------------------------------------------- -### Portability: +### Portability We have ported this program to a wide variety of systems. Among these are: @@ -152,7 +152,7 @@ these are: - Dynix / Sequent Balance ('cc' for Natl. Semi. base + 'gcc 1.36') - Unicos / Cray 2 -### Obfuscation: +### Obfuscation We (the authors) feel this program is obfuscated for the following reasons: diff --git a/1990/pjr/README.md b/1990/pjr/README.md index 462f00d91..5d296e1f7 100644 --- a/1990/pjr/README.md +++ b/1990/pjr/README.md @@ -51,6 +51,8 @@ to functions! ## Author's remarks: +Rot13: + Vg vf fvzcyr gb znxr gur cebtenz cevag bgure fgevatf. Rnpu nycunorgvpny punenpgre sebz n gb m vf cevagrq bhg nf vgf bccbfvgr: diff --git a/1990/scjones/README.md b/1990/scjones/README.md index c95350842..e1ffcfc23 100644 --- a/1990/scjones/README.md +++ b/1990/scjones/README.md @@ -4,7 +4,7 @@ Larry Jones SDRC 2000 Eastman Dr Milford, OH 45150 -USA +US ## To build: diff --git a/1990/tbr/README.md b/1990/tbr/README.md index 6068dc980..916b1ae7f 100644 --- a/1990/tbr/README.md +++ b/1990/tbr/README.md @@ -4,13 +4,13 @@ Byron Rakitzis Princeton University 5707 Old Lodge Dr. Houston, TX 77066 -USA +US Sean Dorward Princeton University 10274 Burleigh Cottage Lane Ellicott City, MD 21043 -USA +US ## To build: diff --git a/1990/theorem/README.md b/1990/theorem/README.md index 6dc5e4a37..4b6d753dc 100644 --- a/1990/theorem/README.md +++ b/1990/theorem/README.md @@ -4,7 +4,7 @@ Adrian Mariano University of Washington 2729 72nd Ave SE Mercer Island, WA 98040 -USA +US ## To build: @@ -21,9 +21,9 @@ that dump core when NULL is dereferenced but this problem showed itself in modern systems even with the 4 '0 0 0 0'. He also fixed a segfault if not enough args are specified and fixed the code so that the generated `fibonacci.c` actually works; before it just printed `0` over and over again (since it did not -work anyway a segfault prevention was added here). He also some array addressing -(some of which might not be strictly necessary but as he was testing the -`fibonacci.c` bug he ended up changing it anyway). Finally he changed this +work anyway a segfault prevention was added here). He also fixed some array +addressing (some of which might not be strictly necessary but as he was testing +the `fibonacci.c` bug he ended up changing it anyway). Finally he changed this program to use `fgets()` not `gets()` to make it safer and to prevent a warning about `gets()` at linking or runtime. Thank you Cody for your assistance! @@ -40,12 +40,13 @@ initially. Thank you Yusuke! where: - expression - function f(x,y) (see below) - x1 - start of interval - x2 - end of interval - h - step size - y1 - initial value (y(x1) == y1) - +``` +expression - function f(x,y) (see below) +x1 - start of interval +x2 - end of interval +h - step size +y1 - initial value (y(x1) == y1) +``` ## Try: @@ -65,15 +66,17 @@ The program's source implements four functions, all from the same source file! When you compile theorem.c as is and run with 5 args, it numerically -solves the equation y'=f(x,y), with a step size of h, over the interval -x=[x1,x2], with the initial condition of y(x1)=y1. +solves the equation `y'=f(x,y)`, with a step size of `h`, over the interval +`x=[x1,x2]`, with the initial condition of `y(x1)=y1`. -The 'expression' f(x,y), is any function of 'x' and 'y' with the +The 'expression' `f(x,y)` is any function of `x` and `y` with the operators: - + - * / ^ +``` ++ - * / ^ +``` -The symbol '^' is the power operator. Note that it only supports +The symbol `^` is the power operator. Note that it only supports integer powers. Also note that all expressions are evaluated strictly left to right. (i.e., parenthesis aren't supported). @@ -128,7 +131,7 @@ received a standing ovation; a first for a contest entry. ## Author's remarks: Differential equations are solved via the Runge-Kutta method, which guarantees -local error proportional to h^5, and total error across a finite interval is at +local error proportional to `h^5`, and total error across a finite interval is at most a constant times `h^4`. Sorting is accomplished with a standard shell sort. diff --git a/1990/westley/README.md b/1990/westley/README.md index aa12f16a2..8f8a8f5cf 100644 --- a/1990/westley/README.md +++ b/1990/westley/README.md @@ -4,7 +4,7 @@ Brian Westley (Merlyn LeRoy on usenet) DigiBoard, Inc. 1026 Blair Ave. St. Paul, MN 55104 -USA +US ## To build: @@ -55,18 +55,19 @@ Use `westley.alt` as you would `westley`. ## Judges' remarks: - If you would rather "Daisy" someone other than Westley, rename the program as needed. :-) Read each block of code as if it were a piece of correspondence. For example, the first block of code would read: - charlie, - doubletime me, OXFACE! - not interested, get out - mainly die, charly, *die* - signed charlotte +``` +charlie, + doubletime me, OXFACE! + not interested, get out + mainly die, charly, *die* + signed charlotte +``` The original source had control-L's after each code block. To make it easier on news readers, we converted each control-L to @@ -86,7 +87,7 @@ Lint complains about everything - null effect, xxx may be used before set, statement not reached, return(e) and return. Lint dumps core on some systems. My personal favorite lint complaint is - "warning: eroticism unused in function main". +**_"warning: eroticism unused in function main"._** Also obviously, `(char)lotte` and `(char*)lie` are incompatible types... diff --git a/1991/ant/README.md b/1991/ant/README.md index 84f997fa2..89d442c53 100644 --- a/1991/ant/README.md +++ b/1991/ant/README.md @@ -54,7 +54,7 @@ Carriage return is mapped to newline on input and ignored on output. Tab stops are every eight columns. Non-printable characters may have unpredictable results depending on the implementation of `curses`. -### COMMANDS: +### Commands - h j k l left, down, up, right cursor movement - H J K L word left, page down, page up, word right @@ -66,13 +66,13 @@ results depending on the implementation of `curses`. - R refresh the screen - Q quit -### EXIT STATUS: +### Exit status - 0 success - 2 missing edit filename -### ABOUT THIS ENTRY: +### About this entry The BUF size should be set at compile time to 32767. This value was used because the Sozobon C compiler for the Atari ST has 16 bit ints and a limit on @@ -102,7 +102,7 @@ in the same group every so often. This entry will display a file with long lines, but has trouble scrolling the screen with long lines. Paging up and down should work correctly, however. -### REFERENCES: +### References: [Fin80] Craig A. Finseth, "Theory and Practice of Text Editors or A Cookbook For An EMACS", TM-165, MIT Lab. for Computer diff --git a/1991/brnstnd/README.md b/1991/brnstnd/README.md index 96d683789..436a7b453 100644 --- a/1991/brnstnd/README.md +++ b/1991/brnstnd/README.md @@ -77,7 +77,7 @@ Here, then, is the SORTA programming language. All non-digits delimit numeric constants. Spaces and newlines are ignored except as numeric delimiters. -### Basic operations: +### Basic operations - `q`: quit - `number`: push that number on top of the i stack @@ -107,7 +107,7 @@ delimiters. Note that nand is sufficient to construct all bitwise operations, as demonstrated by icalc below. -### System operations: +### System operations - `o`: pop top of `s stack` and top two of `i stack`; `open(s1,i2,i1);` leave result on `i stack` @@ -126,7 +126,7 @@ in the s stack to terminate the argument list. If the execve() fails, any operation involving current members of the s stack has undefined effects, and -1 is pushed onto the i stack. -### High-level language operations: +### High-level language operations - :x: copy the top of the s stack into a program labeled by character x - =x: pop the top of the i stack. If it was nonzero, execute the program diff --git a/1991/buzzard/README.md b/1991/buzzard/README.md index a2ccb32a4..9d7904288 100644 --- a/1991/buzzard/README.md +++ b/1991/buzzard/README.md @@ -4,7 +4,7 @@ Sean Barrett University of Maryland 5407 20th Place Hyattsville MD 20782 -USA +US ## To build: @@ -26,7 +26,7 @@ You are invited to try to cheat, ... if you can figure out how! :-) ## Author's remarks: -### HOW TO PLAY: +### How to play When the game starts, you are at the far end of the maze from the exit, looking down a corridor. To move forward, type `f` and press @@ -37,7 +37,9 @@ after all the moves. The game ends if you get out the exit (you'll know it when you see it) or when you type `^D` (EOF). -### HINTS ON HOW TO CHEAT: (rot13 to read) +### Hints on how to cheat + +Rot13 to read: Lbh pna, bs pbhefr, purng ol ybbxvat ng gur znmr znc. Gur dhrfgvba lbh arrq gb nfx lbhefrys, gubhtu, vf jung frdhrapr bs punenpgref @@ -48,7 +50,9 @@ it) or when you type `^D` (EOF). gura onpxjneq sebz gur pheerag cbfvgvba gb qenj gur yrsg fvqr naq gura gur evtug fvqr. -### ADVANCED USAGE NOTES: (rot13 to read) +### Advanced usage notes + +Rot13 to read: Gur cebtenz pna nyfb or eha sebz bgure svyrf pbagnvavat znmrf. Gur znmr fubhyq or ynvq bhg tencuvpnyyl va gur boivbhf sbezng; arjyvarf diff --git a/1991/cdupont/README.md b/1991/cdupont/README.md index de0bfd2d4..641292a06 100644 --- a/1991/cdupont/README.md +++ b/1991/cdupont/README.md @@ -23,9 +23,9 @@ make all Why is the following label necessary? - - sorryfor_this_unused_but_very_needed_label: - +```c +sorryfor_this_unused_but_very_needed_label: +``` Notice that if you C beautify (cb) or pre-process this program, it will no longer work correctly, or at all. (go ahead, try it... :-)) diff --git a/1991/davidguy/README.md b/1991/davidguy/README.md index 106eab808..33bc3d909 100644 --- a/1991/davidguy/README.md +++ b/1991/davidguy/README.md @@ -4,14 +4,14 @@ David Applegate School of Computer Science Carnegie Mellon University Pittsburgh PA 15213 -USA +US Guy Jacobson AT&T Bell Laboratories 600 Mountain Avenue Murray Hill NJ 07974 -USA +US ## To build: diff --git a/1991/dds/README.md b/1991/dds/README.md index 83d4f5952..cd826b25a 100644 --- a/1991/dds/README.md +++ b/1991/dds/README.md @@ -16,35 +16,51 @@ make all ## To run: ```sh -./dds basic_program -./a.out +./dds basic_program 2>/dev/null +./a.out 2>/dev/null ``` -[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed some segfaults in -this entry as well as making it so `a` (was `a.out`, see below) can be generated -(as in the program did not work, at least with clang). The alternative code, -described below, is what is needed for clang. Reading it might be instructive -even if you have gcc. +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed a segfault that +prevented this entry from working at all and made an alternate version +that works with `clang`. The alternate code, described below, is what is needed +for clang. Reading it might be instructive even if you have gcc. -The first segfault which was always triggered was due to the code `*q>' -'&&(*q)--;`. This seems odd at first glance but it's pointing to `s` which was -read-only memory as a `char *s`. It's now a `char s[]`. The second and third -segfaults were caused if a file was not specified (or it the one specified did -not exist or couldn't be opened for some reason) and if the output file could -not be opened for writing. +The segfault which was always triggered was due to the code `*q>' '&&(*q)--;`. +This seems odd at first glance but it's pointing to `s` which was read-only +memory as a `char *s`. It's now a `char s[]`. Thank you Cody for your assistance! +### INABIAF - it's not a bug it's a feature! :-) + +Please note that if the BASIC file cannot be opened for reading or the output +file cannot be opened for writing then this program will crash. These crashes +are a mild nuisance but are considered a feature not a bug. We challenge you to +fix it for learning if you wish. See also [bugs.md](/bugs.md). + ## Try: With gcc, make and run as follows: - - make dds + +```sh +make dds +``` For example, the author suggests trying: - - ./dds LANDER.BAS - ./a.out + +```sh +./dds LANDER.BAS 2>/dev/null +./a.out 2>/dev/null +``` + +What happens if you give the program a C program like itself? Try: + +```sh +./dds dds.c 2>/dev/null +``` + +You'll get errors yes but what does the generated file look like? What about +other types of files? ### Alternative code: @@ -55,12 +71,13 @@ not messing with the `s` string which is quite complicated. For all Cody knows even changing the length could break functionality and indeed the length would have to be longer for this to work with clang. -How does it work? The code, which you will see in `dds.c`, `return system(q-6);` -equates to `return system("cc a.c");` but clang by default, at least in macOS, -has default -Werror and there were some warnings. This means that the -compilation failed with clang. In particular it would fail (at least with -`LANDER.BAS`) due to a return from `main()` without a return value and the use -of functions not yet declared. +How does it work? The code (which you will see in [dds.c](dds.c)) does a `return +system(q-6);` which equates to `return system("cc a.c");` but clang by default, +at least in macOS, has default -Werror and there were some warnings. This means +that the compilation failed with clang (because it didn't use `make` so no +[Makefile](Makefile) was used). In particular it would fail (at least with +[LANDER.BAS](LANDER.BAS)) due to a return from `main()` without a return value +and the use of functions not yet declared. Now as noted since the string `s` is complicated and because Cody did not want to inadvertently mess something up he changed that code to `system("make a");` @@ -72,8 +89,8 @@ version: ```sh make clobber alt -./dds.alt LANDER.BAS -./a +./dds.alt LANDER.BAS 2>/dev/null +./a 2>/dev/null ``` Thank you Cody for your assistance! diff --git a/1991/dds/dds.alt.c b/1991/dds/dds.alt.c index 6956c2d9d..4ae041ae1 100644 --- a/1991/dds/dds.alt.c +++ b/1991/dds/dds.alt.c @@ -10,8 +10,8 @@ R%PN4\nQaP2Q,2aP4Hb%OD12D12N2!N3\nJVP3Q,,n\ aP1Q*aHb%FN1\nQm>::::aHC%VP3Q>bupj)hfut)c**aHb%JD12JON1!Qjg)a%LN1UP1D12JIQUa\ P1HL%IQ*m>aN2!N2\nP2QP2Q>aN2\nP2Hbdd!b/d";int k;char R[4][99] ;main(c,v)char**v;{char*p,*r,*q;for(q=s;*q;q++)*q>' '&&(*q)--;{FILE*i=fopen(v -[1],"r"),*o=fopen(q-3,"w");if(!i||!o)return 1;for(p=s;;p++)switch(*p++){B'M': -Q(k=fgetc(i))!=EOF&&k!=*p)*r++=k;if(k==EOF){fputs("}}\n",o);fclose(o);return -system("make a");}*r=0 B'P':while(*p!='`')fputc(*p++,o)B'O':Q*r)fputc(*r++,o); -p--B'C':k=0;Q k<*p-'0')(*r++=fgetc(i),k++);*r=0 B'I':k= *p;if(**R==k)goto G -B'G':k= *p;G:p=s;while(*p!='$'||p[1]!= k)p++;p++B'N':R[*p-'0'][0]++;}}} +[1],"r"),*o=fopen(q-3,"w");for(p=s;;p++)switch(*p++){B'M':Q(k=fgetc(i))!=EOF +&&k!=*p)*r++=k;if(k==EOF){fputs("}}\n",o);fclose(o);return system("make a");}*r=0 +B'P':while(*p!='`')fputc(*p++,o)B'O':Q*r)fputc(*r++,o);p--B'C':k=0;Q k<*p-'0' +)(*r++=fgetc(i),k++);*r=0 B'I':k= *p;if(**R==k)goto G B'G':k= *p;G:p=s;while( +*p!='$'||p[1]!= k)p++;p++B'N':R[*p-'0'][0]++;}}} diff --git a/1991/dds/dds.c b/1991/dds/dds.c index 888ff412b..504cc658c 100644 --- a/1991/dds/dds.c +++ b/1991/dds/dds.c @@ -10,8 +10,8 @@ R%PN4\nQaP2Q,2aP4Hb%OD12D12N2!N3\nJVP3Q,,n\ aP1Q*aHb%FN1\nQm>::::aHC%VP3Q>bupj)hfut)c**aHb%JD12JON1!Qjg)a%LN1UP1D12JIQUa\ P1HL%IQ*m>aN2!N2\nP2QP2Q>aN2\nP2Hbdd!b/d";int k;char R[4][99] ;main(c,v)char**v;{char*p,*r,*q;for(q=s;*q;q++)*q>' '&&(*q)--;{FILE*i=fopen(v -[1],"r"),*o=fopen(q-3,"w");if(!i||!o)return 1;for(p=s;;p++)switch(*p++){B'M': -Q(k=fgetc(i))!=EOF&&k!=*p)*r++=k;if(k==EOF){fputs("}}\n",o);fclose(o);return -system(q-6);}*r=0 B'P':while(*p!='`')fputc(*p++,o)B'O':Q*r)fputc(*r++,o); -p--B'C':k=0;Q k<*p-'0')(*r++=fgetc(i),k++);*r=0 B'I':k= *p;if(**R==k)goto G -B'G':k= *p;G:p=s;while(*p!='$'||p[1]!= k)p++;p++B'N':R[*p-'0'][0]++;}}} +[1],"r"),*o=fopen(q-3,"w");for(p=s;;p++)switch(*p++){B'M':Q(k=fgetc(i))!=EOF +&&k!=*p)*r++=k;if(k==EOF){fputs("}}\n",o);fclose(o);return system(q-6);}*r=0 +B'P':while(*p!='`')fputc(*p++,o)B'O':Q*r)fputc(*r++,o);p--B'C':k=0;Q k<*p-'0' +)(*r++=fgetc(i),k++);*r=0 B'I':k= *p;if(**R==k)goto G B'G':k= *p;G:p=s;while( +*p!='$'||p[1]!= k)p++;p++B'N':R[*p-'0'][0]++;}}} diff --git a/1991/fine/README.md b/1991/fine/README.md index 716380f26..570cada52 100644 --- a/1991/fine/README.md +++ b/1991/fine/README.md @@ -5,7 +5,7 @@ Ohio State University Department of Computer and Information Science 2036 Neil Avenue Mall Columbus, Ohio 43210 -USA +US ## To build: @@ -37,8 +37,8 @@ Read the last line backwards! Credit goes to [Merlyn LeRoy (Brian Westley)](/winners.html#Brian_Westley) for that. See his 22 August 1992 [rec.puzzles post](https://groups.google.com/g/rec.puzzles/c/z_xVPMRVBtg/m/lyEYSAeBD4gJ). To -those who have a harder time reading backwards it says: `Gary lent the rug` -from `the rug gary lent`! +those who have a harder time reading backwards it says: `Gary lent the rug`, +rotated from `the rug gary lent`! ## Judges' remarks: @@ -54,7 +54,7 @@ How does this program work? Which 3 bytes of C code can be changed into 2 bytes, allowing the program to still work, but also stripping the high bit off of some input? -## Author's remarks +## Author's remarks: The author wishes to thank J Greely for the last 6 bytes. diff --git a/1991/westley/README.md b/1991/westley/README.md index 567ec3442..2e505d628 100644 --- a/1991/westley/README.md +++ b/1991/westley/README.md @@ -4,7 +4,7 @@ Brian Westley (Merlyn LeRoy on usenet) DigiBoard, Inc. 1026 Blair Ave. St. Paul, MN 55104 -USA +US ## To build: diff --git a/1992/adrian/README.md b/1992/adrian/README.md index 99d428464..1c823a263 100644 --- a/1992/adrian/README.md +++ b/1992/adrian/README.md @@ -4,7 +4,7 @@ Adrian Mariano University of Washington 2729 72nd Ave SE Mercer Island, WA 98040 -USA +US ## To build: @@ -15,16 +15,16 @@ make all [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) changed the location that it used `gets()` to be `fgets()` instead to make it safer and to prevent -any warnings during linking or runtime. One might think that simply changing the -gets() to fgets() (with stdin) would work but it did not because `fgets()` -stores the newline and `gets()` does not. The code was relying on not having -this newline. With `fgets()` the code `if(A(Y)) puts(Y);` ended up printing an -extra line which made the generation of some files (like `adhead.c`) fail to -compile (`gets()` does not store the newline but `fgets()` does). Why? There was -a blank line after a `\` at the end of the first line of a macro definition! -Thus the code now first trims off the last character of the buffer read to get -the same correct functionality but in a safe way. Thank you Cody for your -assistance! +annoying warnings during compiling, linking or runtime (interspersed with the +program's output). One might think that simply changing the gets() to fgets() +(with stdin) would work but it did not because `fgets()` stores the newline and +`gets()` does not. The code was relying on not having this newline. With +`fgets()` the code `if(A(Y)) puts(Y);` ended up printing an extra line which +made the generation of some files (like `adhead.c`) fail to compile (`gets()` +does not store the newline but `fgets()` does). Why? There was a blank line +after a `\` at the end of the first line of a macro definition! Thus the code +now first trims off the last character of the buffer read to get the same +correct functionality but in a safe way. Thank you Cody for your assistance! ## Try: diff --git a/1992/albert/README.md b/1992/albert/README.md index af8202625..d16ebdeae 100644 --- a/1992/albert/README.md +++ b/1992/albert/README.md @@ -47,8 +47,8 @@ Both albert and albert.orig loop without printing anything, although the first factor is 101 and is usually found in an instant. ``` -The `albert.c` file is the fixed file, whereas the `albert.alt.c` -is the file before applying Leo Broukhis' fix. +The [albert.c](albert.c) file is the fixed file, whereas the +[albert.alt.c](albert.alt.c) is the file before applying Leo Broukhis' fix. To compile this alternate version: @@ -119,7 +119,7 @@ destroy some of the lay out. Running the program through lint shows the usual remarks for a K&R program. Defeating this through casts does not make a program cleaner in my opinion. -### Hints: +### Hints Here are some hints, but they may not be too helpful: diff --git a/1992/buzzard.1/README.md b/1992/buzzard.1/README.md index 403c3cc52..add45a284 100644 --- a/1992/buzzard.1/README.md +++ b/1992/buzzard.1/README.md @@ -4,7 +4,7 @@ Sean Barrett Software Construction Company 430 Southwest Parkway, #1906 College Station, TX 77840 -USA +US ## To build: @@ -13,7 +13,7 @@ USA make all ``` -## To run +## To run: ```sh ./buzzard.1 num num @@ -52,13 +52,13 @@ What you shouldn't think about `buzzard.1`: I didn't just submit the post-C-preprocessed output as an entry. -#### Cute trick warning: +#### Cute trick warning `buzzard.1` contains only a numeric printf, yet sometimes it prints out short strings. -### What it does: +### What it does `buzzard.1` is a simple mathematical program. It expects two numeric arguments. @@ -86,7 +86,7 @@ If the first argument is less than 0, it prints out an error message. -### What it is: +### What it is `buzzard.1` is a translator from a pseudo-assembly language into a subset of C suitable for execution on Charles Babbage's Analytical Engine. Or rather, the @@ -100,22 +100,22 @@ could have been simulated on the AE by connecting the already-processed card stack to the input card stack. -### How to try to understand it: +### How to try to understand it *Don't* expand the `#define`s! Rather, decipher what they do. Some of them are mere obfuscation fodder, put in to encourage you to run it through CPP. -### What it doesn't quite do right as an emulator: +### What it doesn't quite do right as an emulator Because of the definitional constraints, calls to `atoi(argv[#])` also appear -inside the loop. These could be put outside-- the initial values of the +inside the loop. These could be put outside--the initial values of the "registers" on the AE--but the macro conventions being used didn't lend themselves to it. -### Theoretical observations: +### Theoretical observations The simulated comparison operations only work with a certain range of numbers; numbers that are too large will cause the output code to fail to simulate the @@ -130,7 +130,7 @@ simulate any existing machine--although not quickly). This would be a good place to site some references on the AE, but I don't have any. -### Definition of the input language to buzzard.1 (OR What Exactly Do All The Macros Do?): +### Definition of the input language to buzzard.1 (OR What Exactly Do All The Macros Do?) [Don't read this unless you're stumped!] diff --git a/1992/buzzard.2/README.md b/1992/buzzard.2/README.md index 9bc4b0e60..0245fb876 100644 --- a/1992/buzzard.2/README.md +++ b/1992/buzzard.2/README.md @@ -4,7 +4,7 @@ Sean Barrett Software Construction Company 430 Southwest Parkway, #1906 College Station, TX 77840 -USA +US ## To build: @@ -67,7 +67,7 @@ Have fun! ## Author's remarks: -### What it does: +### What it does `first` implements a relatively primitive stack machine. How primitive? It supplies 13 visible primitives: 3 arithmetic, @@ -88,7 +88,7 @@ are below, and the interesting property is discussed much further down. -### How to run it: +### How to run it `first` expects you to first enter the names of the 13 primitives, separated by whitespace--it doesn't care what you name them, but @@ -129,7 +129,7 @@ reimplementing all of first and third a second time--I did not care to tackle this project. -### Compiling: +### Compiling `first` is reasonably portable. You may need to adjust the size of the buffers on smaller machines; `m[]` needs to be at least 2000 long, though. diff --git a/1992/gson/README.md b/1992/gson/README.md index e6c06783d..36d05923d 100644 --- a/1992/gson/README.md +++ b/1992/gson/README.md @@ -40,10 +40,10 @@ Determine where your system dictionary is located. You may find it located in one of the following places: ``` - /usr/share/dict/words - /usr/share/lib/spell/words - /usr/ucblib/dict/words - /dev/null # <-- for machines with nothing to say +/usr/share/dict/words +/usr/share/lib/spell/words +/usr/ucblib/dict/words +/dev/null # <-- for machines with nothing to say ``` Then using the proper dictionary: @@ -83,13 +83,13 @@ construed to mean Alphabet Game, and by pure coincidence it happens to be the author's initials. -### What it does: +### What it does AG takes one or more words as arguments, and tries to find anagrams of those words, i.e. words or sentences containing exactly the same letters. -### How to use it: +### How to use it To run AG, you need a dictionary file consisting of distinct words in the natural language of your choice, one word on each line. If your machine doesn't @@ -113,7 +113,7 @@ number of words in the anagrams is limited to 3 by default. This limit can be changed using a numeric command line option, as in `./ag -4 international obfuscated c code contest ## To build: @@ -21,7 +21,7 @@ not segfault if not enough args were specified. He did the same for the alternative version (see below) provided by the author (the original can be seen in the author's remarks below). Thank you Cody for your assistance! -## To run +## To run: If lost: @@ -50,7 +50,7 @@ show correctly! ### Alternative code: -The author provided a version for the USA. To build: +The author provided a version for the US. To build: ```sh make alt @@ -143,7 +143,7 @@ is reasonably accurate. - Beijing 40 116 - Tokyo 36 140 -For a domestic (USA) version with higher resolution, try: +For a domestic (US) version with higher resolution, try: ```c main(l,a,n,d)char**a;{for(d=atoi(a[1])/2*80-atoi(a[2])-2043; diff --git a/1993/cmills/README.md b/1993/cmills/README.md index 98d178197..c9213d6de 100644 --- a/1993/cmills/README.md +++ b/1993/cmills/README.md @@ -4,7 +4,7 @@ Chris Mills Pagine Corporation 1961-A Concourse Drive San Jose, CA 95131 -USA +US ## To build: diff --git a/1993/dgibson/README.md b/1993/dgibson/README.md index dfd8d41fa..2f9a58128 100644 --- a/1993/dgibson/README.md +++ b/1993/dgibson/README.md @@ -21,7 +21,7 @@ make all where: -`datafile` is the initial pattern (default: dgibson.data1) +`datafile` is the initial pattern (default: [dgibson.data1](dgibson.data1)) ## Try: @@ -59,7 +59,7 @@ 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: +### Some notes - the "STAT n" information does not have to be present in the initial configuration diff --git a/1993/ejb/README.md b/1993/ejb/README.md index e5a548aef..2bed24a5f 100644 --- a/1993/ejb/README.md +++ b/1993/ejb/README.md @@ -1,22 +1,28 @@ # Best Obfuscated Algorithm - E. Jay Berkenbilt - Engineering Research Associates - 1595 Springhill Road - Vienna, VA 22182-2235 - USA +E. Jay Berkenbilt +Engineering Research Associates +1595 Springhill Road +Vienna, VA 22182-2235 +US ## To build: - make all +```sh +make all +``` ## To run: - ./ejb level +```sh +./ejb level +``` where: - level a value from -128 to 127 +```sh +level a value from -128 to 127 +``` ## Judges' remarks: @@ -33,20 +39,22 @@ We note that this also works under macOS just fine. ## Author's remarks -WHAT THIS PROGRAM DOES -====================== +### What this program does -### Output solution to Towers of Hanoi for five rings: +#### Output solution to Towers of Hanoi for five rings: - ./ejb 5 +```sh +./ejb 5 +``` The format of the output for the Towers of Hanoi case is simply a text description of how to solve the puzzle. -### Output solution to the Patience puzzle for six rings: +#### Output solution to the Patience puzzle for six rings: - - ./ejb -6 +```sh +./ejb -6 +``` For the patience puzzle, the output is a sequence binary codes representing @@ -55,8 +63,7 @@ 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 -========== +### Motivation Most people who have written software for other people have been asked to count lines of code. Naturally, this brings up the @@ -66,25 +73,24 @@ 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 +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 +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. +Although this program has only been tested on UNIX systems it 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 and CC BY-SA 4.0 License: diff --git a/1993/jonth/README.md b/1993/jonth/README.md index e634f3250..f199b4855 100644 --- a/1993/jonth/README.md +++ b/1993/jonth/README.md @@ -1,14 +1,16 @@ # Most Obfuscated X Program -Jon Thingvold -University of Oslo -Sogn Studentby 8231 -N 0858 Oslo -Norway +Jon Thingvold +University of Oslo +Sogn Studentby 8231 +N 0858 Oslo +Norway ## To build: - make all +```sh +make all +``` NOTE: this entry requires `X11/Xlib.h` header file and the X11 library to compile. macOS users running Mountain Lion and later will need to download and @@ -33,11 +35,13 @@ prepended to them. Thank you Yusuke and Cody for your assistance! ## To run: - ./jonth # must be run on an X11 server +```sh +./jonth # must be run on an X11 server +``` ## Judges' remarks: -Use 'h' and 'l' to shift objects left or right. Use 'k' to +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 @@ -52,7 +56,7 @@ 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 *)`. +This program will not work on machines where `sizeof(int)!=sizeof(void *)`. ## Copyright and CC BY-SA 4.0 License: diff --git a/1993/leo/Makefile b/1993/leo/Makefile index cac73d755..ea6f1a888 100644 --- a/1993/leo/Makefile +++ b/1993/leo/Makefile @@ -114,14 +114,14 @@ DATA= TARGET= ${PROG} # ALT_OBJ= -ALT_TARGET= +ALT_TARGET= mind ################# # build the entry ################# # -all: data ${TARGET} +all: data ${TARGET} ${ALT_TARGET} @${TRUE} .PHONY: all alt data everything clean clobber install \ diff --git a/1993/leo/README.md b/1993/leo/README.md index 263d770e7..1f5e333b2 100644 --- a/1993/leo/README.md +++ b/1993/leo/README.md @@ -1,14 +1,16 @@ # Best Game - Leonid A. Broukhis - Moscow Centre of SPARC Technology - 123481 Liberty St., - 89-1-95 Moscow - Russia +Leonid A. Broukhis +Moscow Centre of SPARC Technology +123481 Liberty St., +89-1-95 Moscow +Russia ## To build: - make all +```sh +make all +``` [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed this to work with modern compilers. Thank you Cody! @@ -18,19 +20,23 @@ modern compilers. Thank you Cody! To have the computer guess: - ./leo [colors] +```sh +./leo [colors] +``` To guess the computer's number: - ./mind [colors] +```sh +./mind [colors] +``` where: - colors number of possible colors (1 to 15) (default: 6) +[colors] is the number of possible colors (1 to 15) (default: 6) ## Judges' remarks: -By default, the number of colors if 6. You may specify a +By default, the number of colors is 6. You may specify a value of between 1 and 15 colors. See the author's notes for instructions of how to play. @@ -39,8 +45,9 @@ International Internet community. ## Author's remarks: -This program plays mastermind, if you call it by a name ending by -'d', otherwise it _solves_ mastermind. Call it without parameters +This program plays +[Mastermind](https://en.wikipedia.org/wiki/Mastermind_(board_game), 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). @@ -48,14 +55,14 @@ 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. +it means that you're mistaken in your answers to its question(s). 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 +solver, and the only place where it makes a difference is the interactive part. Many obfuscations have been made to achieve -this. An expression giving (bulls * 16 + cows) from two numbers +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. @@ -66,35 +73,39 @@ backspaces. Do "disable scrolling" on cmdtool or similar emulators. #### Bugs: Please don't type ^D at the prompt!! -##### EXAMPLE: Suppose we think of 1234: +##### 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 +``` +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: +##### 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 +``` +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 and CC BY-SA 4.0 License: diff --git a/1993/lmfjyh/README.md b/1993/lmfjyh/README.md index 7838d3f4d..6f1052740 100644 --- a/1993/lmfjyh/README.md +++ b/1993/lmfjyh/README.md @@ -1,9 +1,9 @@ # Most Versatile Source - Jyrki Holopainen - Oy LM Ericsson Ab - SF-02420 Jorvas - Finland +Jyrki Holopainen +Oy LM Ericsson Ab +SF-02420 Jorvas +Finland ## To build: @@ -17,23 +17,23 @@ option `-inum` with `find` with the delete option after finding the inode with `ls -li` or else use a GUI to do it. Should you wish to try compiling it you might see something like: - NOTE: This will not compile when using modern compilers because - it relies on a compiler bug which was fixed in gcc 2.3.3 (a very - long time ago now). - rm -f \"\;main\(\)\{puts\(\"Hello\ World!\"\)\;\}char\*C=\".c - cp lmfjyh.c \"\;main\(\)\{puts\(\"Hello\ World!\"\)\;\}char\*C=\".c - cc -std=gnu90 -Wall -Wextra -pedantic -include stdio.h -O3 \ - \"\;main\(\)\{puts\(\"Hello\ World!\"\)\;\}char\*C=\".c -o lmfjyh - Undefined symbols for architecture arm64: - "_main", referenced from: - implicit entry/start for main executable - ld: symbol(s) not found for architecture arm64 - clang: error: linker command failed with exit code 1 (use -v to see invocation) - make: *** [lmfjyh] Error 1 - -and the bogus file will be: - - ";main(){puts("Hello World!");}char*C=".c +```sh +$ make all +NOTE: This will not compile when using modern compilers because +it relies on a compiler bug which was fixed in gcc 2.3.3 (a very +long time ago now). +rm -f \"\;main\(\)\{puts\(\"Hello\ World!\"\)\;\}char\*C=\".c +cp lmfjyh.c \"\;main\(\)\{puts\(\"Hello\ World!\"\)\;\}char\*C=\".c +cc -std=gnu90 -Wall -Wextra -pedantic -include stdio.h -O3 \ + \"\;main\(\)\{puts\(\"Hello\ World!\"\)\;\}char\*C=\".c -o lmfjyh +Undefined symbols for architecture arm64: + "_main", referenced from: + implicit entry/start for main executable +ld: symbol(s) not found for architecture arm64 +clang: error: linker command failed with exit code 1 (use -v to see invocation) +make: *** [lmfjyh] Error 1 +``` +and the bogus file will be `";main(){puts("Hello World!");}char*C=".c`. For an explanation of why this is see the author's remarks. @@ -41,14 +41,16 @@ For an explanation of why this is see the author's remarks. If you have gcc < 2.3.3: - ./lmfjyh +```sh +./lmfjyh +``` ## Judges' remarks: There's more than one way to get around disk quotas. :-) -## Author's remarks; +## Author's remarks: "Practical and efficient method of compressing source code". @@ -61,34 +63,36 @@ 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: +#### Listing 1: A simple "Hello World" program - main() - { - puts("Hello World!"); - } - +```c +main() +{ + puts("Hello World!"); +} +``` ### 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. +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": +#### Listing 2: Compressed "Hello world" - - char*_=__FILE__; +```c +char*_=__FILE__; +``` -Listing 3. Code embedded in the file name: +#### Listing 3: Code embedded in the file name - - ";main(){puts("Hello World!");}char*C=".c +```c +";main(){puts("Hello World!");}char*C=".c +``` The sample program in listing 1 is 36 bytes long. By using the new @@ -97,12 +101,12 @@ 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. +megabyte of source code file 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 +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. @@ -111,12 +115,12 @@ code in a source file as presented in listing 1. ### 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 +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 +part of a comment start and end identifier. This, however, is 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 @@ -127,7 +131,7 @@ 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. +code needs be recompiled after changes have been made. ### Usage with currently available tools @@ -136,30 +140,30 @@ 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) +system should be able to compile the code (there might be problems +with some older UNIX variants). -### Compilers: +### 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) +- 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 +- cc (SunOS/Solaris) - could not start cpp properly +- cc/xlc (AIX) - could not open source -### Other tools: +### Other tools -#### Debuggers: (tested at SunOs 4.1.2) +#### Debuggers: (tested at SunOS 4.1.2) -dbx - Quit with a very 'informative' error message: - "dbx: fatal error: Is a directory" +- dbx - Quit with a very 'informative' error message: + "dbx: fatal error: Is a directory" -gdb - Printed almost the same error message ":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. @@ -170,7 +174,7 @@ None of the lints tested environments were able to parse the file. ### Conclusions -The method can be used to compress any types of files, actually the +The method can be used to compress any types of files and 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 diff --git a/1993/plummer/README.md b/1993/plummer/README.md index 9349e3dee..cfbab66a7 100644 --- a/1993/plummer/README.md +++ b/1993/plummer/README.md @@ -1,22 +1,26 @@ # Best One Liner - Mark Plummer - 2901 Reckord Road - Fallston, MD, 21047 - USA +Mark Plummer +2901 Reckord Road +Fallston, MD, 21047 +US ## To build: - make all +```sh +make all +``` ## To run: - ./plummer number arg +```sh +./plummer number arg +``` where: - number is a number (try 21701) - arg is any argument +- number is a number (try 21701) +- arg is any argument ### INABIAF - it's not a bug it's a feature :-) @@ -33,31 +37,31 @@ characters, and why? 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 +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 _ +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`). +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 +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 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 +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 @@ -66,7 +70,7 @@ 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 +string. In the test portion, `_` is ensured 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, diff --git a/1993/rince/README.md b/1993/rince/README.md index e888c94b1..1e91c8620 100644 --- a/1993/rince/README.md +++ b/1993/rince/README.md @@ -1,74 +1,81 @@ # Most Well Rounded - James Bonfield - MRC Laboratory of Molecular Biology, - Hills Road, - Cambridge, - England +James Bonfield +MRC Laboratory of Molecular Biology, +Hills Road +Cambridge +England ## To build: - make all +```sh +make all +``` [Yusuke Endoh](/winners.html#Yusuke_Endoh) supplied a patch to get this to work in modern systems. Thank you Yusuke! - - ## To run: - ./rince [cabbage] +```sh +./rince [cabbage] +``` where: - [cabbage] a CABBAGE description file (default: `rince.c`) - - - - - + +`[cabbage]` is a CABBAGE description file (default: `rince.c`) ## Judges' remarks: 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.data1](rince.data1) plays +[Breakout](https://en.wikipedia.org/wiki/Breakout_(video_game). Keys are `,` +for left, `/` for right, and `.` for 'fire the ball'. -- `rince.data2` plays the old rince game from IOCCC 1991. +- [rince.data2](rince.data2) plays the old [Rince](/1991/rince/rince.c) +([README.md](/1991/rince/README.md) 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.data3](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. +- [rince.data4](rince.data4) Sokoban screen 13. Same rules as above. -For a brief design description, see [rince.design](rince.design). +For a brief design description, see [design.md](design.md). The `select(2)` from SunOS says: - BUGS +``` +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. +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 +Systems such as Linux do 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) - +```c +select(k,&y,0,0,&v) +``` + should be replaced with: - select(k,&y,0,0,(v.tv_usec=1< + + 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 a space ship (as in the [Space +Invaders](https://en.wikipedia.org/wiki/Space_Invaders) 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 `*1` should +be used instead. Now the format of the game description file is now +the following: (angle brackets denote an 'entity' to be defined). + + +``` + *\n*\n[ \t]+\n + +``` + +The `` should take into account the newline at the end of each line +of map, and hence should also be one larger than expected. diff --git a/1993/rince/rince.design b/1993/rince/rince.design deleted file mode 100644 index 67a451643..000000000 --- a/1993/rince/rince.design +++ /dev/null @@ -1,84 +0,0 @@ - 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). - - *\n*\n[ \t]+\n - - - The should take into account the newline at the end of each line - of map, and hence should also be one larger than expected. diff --git a/1993/schnitzi/README.md b/1993/schnitzi/README.md index 10d712b79..ba0f07494 100644 --- a/1993/schnitzi/README.md +++ b/1993/schnitzi/README.md @@ -3,67 +3,81 @@ Mark Schnitzius 1700 Woodbury Rd. #1208 Orlando, FL 32828 -USA +US ## To build: - make all +```sh +make all +``` [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) made this use `fgets()` -not `gets()` to make it safer and to prevent a warning with linking or at -runtime. Thank you Cody for your assistance! +not `gets()` to make it safer and to prevent an annoying warning with compiling +and/or linking and/or runtime, the latter of which is interspersed with the +output of the program itself. Thank you Cody for your assistance! ## To run: - ./schnitzi file - -where: - - file a file containing some text +```sh +./schnitzi file +``` -NOTE: this entry will segfault if the file cannot be opened. +where + + +`file` is a file containing some text. + +### INABIAF - it's not a bug it's a feature! :-) + +This entry will segfault if the file cannot be opened. This is not a bug. ## Try: - ./schnitzi schnitzi.info - # ask some questions suggested by the author, noted below +```sh +./schnitzi schnitzi.info +# ask some questions suggested by the author, noted below +``` We also suggest you ask the program: - Who is Mark Schnitzus? +```sh +Who is Mark Schnitzus? +``` Notice how it still manages to answer the question despite there being an intentional spelling error there. Try feeding the program source to the program and ask both: - What is cat ? - What is cat? - +```sh +What is cat ? +What is cat? +``` ## Judges' remarks: 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: +The author suggests the following questions when using +[schnitzi.info](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? +- 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? 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. :-) -NOTE: If you have a ' in the question this entry may fail. +NOTE: If you have a ' in the question this entry might fail. NOTE: The author may also be contacted at: marks@aldrin.ksc.nasa.gov. @@ -88,7 +102,7 @@ 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: +### Compilation notes - The use of 'strcasecmp' may be non-standard. 'strcmp' can be substituted for it, with a slight performance penalty. @@ -97,14 +111,14 @@ it, with a slight performance penalty. argv[0], to hold the name of the executable. It is my understanding that this property of argv[0] is not guaranteed on some systems. -### Obfuscation: +### Obfuscation - It uses a hidden string to test for punctuation. - The layout, variable names, and expression format have been chosen in such a way as to cause visual confusion. -- It uses uses external 'system' calls to echo the text file and break up the +- It uses uses external `system()` calls to echo the text file and break up the question into individual words with a recursive call. - It uses a clever hack to simulate artificial intelligence. diff --git a/1993/vanb/README.md b/1993/vanb/README.md index 1d0569c28..ec7c96480 100644 --- a/1993/vanb/README.md +++ b/1993/vanb/README.md @@ -1,14 +1,16 @@ # Most Irregular Expression - David Van Brackle - ISX Corporation - 1165 Northchase Parkway, Suite 120 - Marietta, GA 30067 - USA +David Van Brackle +ISX Corporation +1165 Northchase Parkway, Suite 120 +Marietta, GA 30067 +US ## To build: - make all +```sh +make all +``` [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed this to work with clang. The problem was that the third arg to main() was not a `char **`. Instead @@ -18,42 +20,50 @@ right parameters. Thank you Cody for your assistance! ## To run: - ./vanb 'exp' - -where 'exp' is an octal expression +```sh +./vanb 'exp' +``` + +where `exp` is an octal expression. See below for how it can also have +hexadecimal and decimal numbers. ## Try: - ./vanb 1+1 +```sh +./vanb '1+1' - ./vanb 4+4 +./vanb '4+4' +``` +What happens if you use something other than valid digits? ## Judges' remarks: 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: () - +``` +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. :-) -## Author's remarks +## Author's remarks: 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. +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: +### 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". @@ -68,133 +78,145 @@ 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 +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). +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: +### How It Works: -It's a recursive descent parser, calling main -for all of its recursion. O2 is a state variable, telling main +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 +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) : +Here's the grammar `('e'` denotes the empty string) : - ::= - ::= + | - | e - ::= - ::= * | / | % | e - ::= + | - | ( | d | D | x | X | - ::= ) - ::= [0-9] | e - ::= [0-9] | [A-F] | [a-f] | e - ::= [0-7] | e - +``` + ::= + ::= + | - | e + ::= + ::= * | / | % | e + ::= + | - | ( | d | D | x | X | + ::= ) + ::= [0-9] | e + ::= [0-9] | [A-F] | [a-f] | e + ::= [0-7] | e +``` Here's how the grammar nonterminals map to octal state numbers: - is 012 - is 011 - is 010 - is 07 - is 06 - is 013 - is 04 - is 05 - is 03 +``` + is 012 + is 011 + is 010 + is 07 + is 06 + is 013 + is 04 + is 05 + 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 +augmented with comments showing where each state begins. `N1` and `N2` are notes: +```c +#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); +} +``` - #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 +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 +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 ``). +printf, and sends the parser to state `012` (which is ``). -The E and T states work like this: +The `E` and `T` states work like this: - int e(){ return eprime( t() ); } +```c +int e(){ return eprime( t() ); } +``` -The E' and T' states work like this: +The `E'` and `T'` states work like this: +```c +int eprime( int intermediate ) +{ + if( ch == '+' ) + { + ch = nextchar(); + return eprime( intermediate + t() ); + } + else return intermediate; +} +``` - 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`): -The D, X and O states work like this (they assume that they're initially -called with 0): +```c +int octal( int intermediate ) +{ + if( ch>='0' && ch<='7' ) + { + intermediate = intermediate * 8 + ch - '0'; + ch = nextchar(); + return octal( intermediate ); + } + else return intermediate; +} - 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. +`F` and `C` work similarly. ## Copyright and CC BY-SA 4.0 License: diff --git a/1994/README.md b/1994/README.md index cf836e967..5f5f74d30 100644 --- a/1994/README.md +++ b/1994/README.md @@ -43,7 +43,7 @@ The ideal 3rd judge would have all of the following: * reasonable written communication skills (able to write README.md files) * appreciation for well-written non-obfuscated code * willing to devote ~4 weekend days in January (starting Jan 96) for judging - * located in the San Francisco (California, USA) Bay Area, or + * located in the San Francisco (California, US) Bay Area, or able to travel (paying your own way) to the SF Bay Area during judging, or able to link to the other IOCCC judges some form of a a video link diff --git a/1994/dodsond1/README.md b/1994/dodsond1/README.md index 2c281a99c..ae6db89bf 100644 --- a/1994/dodsond1/README.md +++ b/1994/dodsond1/README.md @@ -1,20 +1,24 @@ # Best Game -Don Dodson -AG Communication Systems -17239 N. 19th Ave. #1003 -Phoenix, AZ 85023 -USA +Don Dodson +AG Communication Systems +17239 N. 19th Ave. #1003 +Phoenix, AZ 85023 +US ## To build: - make all +```sh +make all +``` -## To run +## To run: - ./dodsond1 - -NOTE: At the prompt, try entering E3. +```sh +./dodsond1 +``` + +NOTE: At the prompt, try entering `E3`. ## Judges' remarks: diff --git a/1994/dodsond2/README.md b/1994/dodsond2/README.md index e6c094ae7..215e3964d 100644 --- a/1994/dodsond2/README.md +++ b/1994/dodsond2/README.md @@ -1,18 +1,22 @@ # Most Obfuscated Packaging -Don Dodson -AG Communication Systems -17239 N. 19th Ave. #1003 -Phoenix, AZ 85023 -USA +Don Dodson +AG Communication Systems +17239 N. 19th Ave. #1003 +Phoenix, AZ 85023 +US ## To build: - make all +```sh +make all +``` ## To run: - ./dodsond2 +```sh +./dodsond2 +``` ## Judges' remarks: @@ -33,9 +37,11 @@ dodsond2.gz: gzip compressed data, last modified: Mon Aug 29 21:54:39 1994, max The [dodsond2.gz](dodsond2.gz) file was submitted as source in an effort to get around the 1994 version of Rule 2: - 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. +``` +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. +``` Indeed, when [dodsond2.gz](dodsond2.gz) is uncompressed, it is identical to the [dodsond2.c](dodsond2.c) file you find today. @@ -58,11 +64,11 @@ be detected from 2 rooms away. To win, you must find one or more arrows, determine where the Wumpus is, and shoot him, all without falling into a pit or becoming the -next meal for the Wumpus. To shoot an arrow, type "s". Then give a +next meal for the Wumpus. To shoot an arrow, type `s`. Then give a list of the rooms you want to shoot into. The rooms must be connected in the order you list them, or else the arrow may bounce back and hit you. An arrow can go through as many as four rooms. -But beware, because shooting an arrow and missing the Wumpus may +But beware that shooting an arrow and missing the Wumpus may awaken him. There is a robber who waits in an unknown room. If you enter @@ -71,8 +77,8 @@ and move to a new room. If he steals all the arrows in the Caverns, you may catch him and recover all of them. Doing this gives you a bonus on your score. -You can quit at any time by typing 'q'. Typing 'i' will tell -you how many arrows you are carrying. 'l' prints the description +You can quit at any time by typing `q`. Typing `i` will tell +you how many arrows you are carrying. `l` prints the description of the current room again. ## Copyright and CC BY-SA 4.0 License: diff --git a/1994/horton/README.md b/1994/horton/README.md index 2e310a871..9c095f495 100644 --- a/1994/horton/README.md +++ b/1994/horton/README.md @@ -1,15 +1,14 @@ # Best Utility -Mark Horton -AT&T Bell Labs -Rm 1H-117 -6200 E Broad St. -Columbus OH 43213 -USA +Mary Ann Horton +US + ## To build: - make all +```sh +make all +``` ## To run: @@ -17,7 +16,12 @@ USA ./horton A B C D ``` -A, B, C, D are numeric arguments. +`A`, `B`, `C` and `D` are numeric arguments. + +### INABIAF - it's not a bug it's a feature! :-) + +Running this program without enough args will very likely crash or do something +else. ## Try: @@ -31,11 +35,11 @@ This confuses cb greatly. See [horton.alt.c](horton.alt.c) for an unobfuscated/e version. To run this alternate version: ```sh -make horton.alt +make alt ./horton.alt A B C D ``` -(Use `horton.alt` as you would `horton` above.) +Use `horton.alt` as you would `horton` above. ## Judges' remarks: @@ -44,9 +48,9 @@ Try to figure out how this program prints, for a given slope, the right character. And for extra credit, try to figure out which character is at the bottom on this hint file. :-) -## Author's remarks +## Author's remarks: -Run it with any 4 numeric arguments, e.g. prog 3 2 1 0. Play with the +Run it with any 4 numeric arguments, e.g. `./horton 3 2 1 0`. Play with the numbers to get a pleasing result, or use it for your high school algebra class. @@ -62,13 +66,17 @@ It's easily modified to graph *any* 96x160 bitmap on a dumb terminal. See the [gtface](gtface.c) program for another example. Try: - make gtface - ./gtface < gtface.data +```sh +make gtface +./gtface < gtface.data +``` For more information, see + Using GraphTab; USENIX ;login: Sept/Oct 1992; Pages 28-31 +``` MMMM,M,MM"MM,,, ,,MMMMMMMMM"""""""", @@ -94,6 +102,7 @@ Sept/Oct 1992; Pages 28-31 ," , "MMMMMMM"MM"M,,,,MMMMM , ,, M ," MMMMMM"MM""M ,MMMMM,M, M , MMMM,MMMM"M"M"M,MM,M,", " +``` ## Copyright and CC BY-SA 4.0 License: diff --git a/1994/imc/README.md b/1994/imc/README.md index b230e6609..0a757f707 100644 --- a/1994/imc/README.md +++ b/1994/imc/README.md @@ -1,28 +1,36 @@ # Most Obfuscated Algorithm -Ian Collier -Oxford University -57 Wyndham Avenue (home address) -BOLTON -BL3 4LG -England +Ian Collier +Oxford University +57 Wyndham Avenue (home address) +Bolton +BL3 4LG +England ## To build: - make all +```sh +make all +``` ## To run: - To use: - ./imc INTEGER +```sh +./imc [NUMBER] +``` + +where `[NUMBER]` is an optional number. Default is 5. ## Try: - ./imc 3 - ./imc 3 - ./imc 4 - ./imc 4 - ./imc 6 +```sh +./imc 3 +./imc 3 +./imc 4 +./imc 4 +./imc 6 +./imc 13 +``` ## Judges' remarks: @@ -32,15 +40,15 @@ This entry's algorithm is as magic as its output! ## Author's remarks: This program may be compiled with an ANSI or K&R compiler. A few -harmless warnings are displayed only if "gcc -Wall" is used. +harmless warnings are displayed only if `gcc -Wall` is used. This entry is really a set of library functions, but an example main function has been added so that the library can be tested. If -the program appears too large, consider that functions o and s can +the program appears too large, consider that functions `o` and `s` can each be separated from the rest of the program (except for the short -functions p and r, which they require) and used alone. However, the -main part of the program is the function e, which does require all the -other functions (apart from main). +functions `p` and `r`, which they require) and used alone. However, the +main part of the program is the function `e`, which does require all the +other functions (apart from `main`). The program should be supplied with an integer parameter. If no parameter or an invalid parameter is given, then 5 is assumed. The @@ -53,22 +61,24 @@ OK, so you have probably seen magic square printers before. But what about one that deals with even sizes as well as odd ones, or one that prints out a different one each time (or attempts to, at any rate)? -I have formatted the important functions o, s and e to show how useful -the word "for" is, and (in function e) how useful the words "if" and +I have formatted the important functions `o`, `s` and `e` to show how useful +the word "for" is, and (in function `e`) how useful the words "if" and "else" are. In fact, hardly anything happens that isn't in one of these instructions. I did this in order to simplify the code - the algorithms used to make the random squares are quite complex without being shrouded in obfuscated code! :-) Incidentally, I was surprised to find out how -useful the exclusive-or operator was while writing function s. +useful the exclusive-or operator was while writing function `s`. Here are the descriptions of the functions in the library: - o(n,a,q,d): makes a magic square of order n when n is odd and at least 3. - s(n,a,q,d): makes a magic square of order n when n equals 4. - e(n,a,q,d): makes a magic square of order n when n is even and at least 6. +``` +o(n,a,q,d): makes a magic square of order n when n is odd and at least 3. +s(n,a,q,d): makes a magic square of order n when n equals 4. +e(n,a,q,d): makes a magic square of order n when n is even and at least 6. +``` -In the above, `a` (of type `int*`) points to an area of memory in which -the magic square will be stored and `q` (also of type `int*`) points to +In the above, `a` (of type `int *`) points to an area of memory in which +the magic square will be stored and `q` (also of type `int *`) points to an area of memory of length at least `n*sizeof(int)` bytes which can be used as a work space. Both `a` and `q` must be allocated by the caller. The integer parameter `d`, usually zero, indicates the length of a gap diff --git a/1994/ldb/Makefile b/1994/ldb/Makefile index d22b3e1b1..23f03d9c9 100644 --- a/1994/ldb/Makefile +++ b/1994/ldb/Makefile @@ -111,8 +111,8 @@ OBJ= ${PROG}.o DATA= TARGET= ${PROG} # -ALT_OBJ= ${PROG}.alt.o -ALT_TARGET= ${PROG}.alt +ALT_OBJ= +ALT_TARGET= # FORCE use of -trigraphs # diff --git a/1994/ldb/README.md b/1994/ldb/README.md index 8df413f27..4e69859c9 100644 --- a/1994/ldb/README.md +++ b/1994/ldb/README.md @@ -1,10 +1,10 @@ # Best One-liner -Laurion Burchall -Brown University -Unit 4641 -Providence RI 02912-4641 -USA +Laurion Burchall +Brown University +Unit 4641 +Providence RI 02912-4641 +US ## To build: @@ -15,17 +15,16 @@ make all [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed this so it would compile and work with modern compilers. The problem was that `srand()` returns void but it was used in a `||` expression. Thus the comma operator was needed. -Cody also changed the entry to use `fgets()` instead of `gets()` to make it -safe for lines greater than 231 in length and to prevent a warning at linking or -at runtime. Note that this now prints a newline after the output but this seems -like a worthy compromise for making it safer (fixing it is more problematic than -it is worth). In macOS another line of output would be shown anyway namely the -warning that it uses gets(). A subtlety about this fix: if a line is greater -than 231 in length if the program chooses that line it might print the first 231 -characters or it might print (up to) the next 231 characters and so on. Thank -you Cody for your assistance! - -For the original fixed version [ldb.alt.c](ldb.alt.c) see below. +Cody also changed the entry to use `fgets()` instead of `gets()` to make it safe +for lines greater than 231 in length and to prevent a warning at linking or at +runtime, the latter of which can be interspersed with output of the program. +Note that this now prints a newline after the output but this seems like a +worthy compromise for making it safer (fixing it is more problematic than it is +worth). In macOS another line of output would be shown anyway namely the warning +that it uses gets(). A subtlety about this fix: if a line is greater than 231 in +length if the program chooses that line it might print the first 231 characters +or it might print (up to) the next 231 characters and so on. Thank you Cody for +your assistance! ## To run: @@ -47,17 +46,6 @@ printf "The International Obfuscated C Code Contest\n by Laurion Burchall" | ./ldb ``` -### Alternate code: - -For the original version fixed so that it will compile with modern compiles, -try: - -```sh -make alt -``` - -Use `ldb.alt` as you would `ldb`. - ## Judges' remarks: Trigraphs are natural obfuscators. Most C-beautifiers become C-uglifiers diff --git a/1994/ldb/ldb.alt.c b/1994/ldb/ldb.alt.c deleted file mode 100644 index 9e7c492bf..000000000 --- a/1994/ldb/ldb.alt.c +++ /dev/null @@ -1 +0,0 @@ -int _,O,__??('}'??);main(){while(O?gets((rand()%O++?':':_)+__)||puts(&__??(_??))&_:(srand(time((O+++_))),0)||O);} diff --git a/1994/schnitzi/README.md b/1994/schnitzi/README.md index 00629ffe8..ebdb2ca82 100644 --- a/1994/schnitzi/README.md +++ b/1994/schnitzi/README.md @@ -4,8 +4,8 @@ Mark Schnitzius ISX Corporation 1165 Northchase Pkwy, Suite 120 Marietta, GA 30067 -USA - +US + ## To build: @@ -32,10 +32,11 @@ it is not as easy to change it to `fgets()`. [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) gives some hints in the [bugs.md](/bugs.md) file on how this entry works which might be useful in order to get this to use `fgets()` which would prevent a warning at linking or -runtime. The file [schnitzi.alt.c](schnitzi.alt.c) has this to get anyone -started, should they wish to tackle it (Cody will in time). The problem with -changing the buffer size is that even when it works the generated output (see -judges' remarks below) will not be 100% correct duplication of the program. +runtime, the latter of which is interspersed with the output of the program. The +file [schnitzi.alt.c](schnitzi.alt.c) has this to get anyone started, should +they wish to tackle it (Cody might in time). The problem with changing the buffer +size is that even when it works the generated output (see judges' remarks below) +will not be 100% correct duplication of the program. ### Alternate code: @@ -69,16 +70,20 @@ down to the bottom right. In other words, the first row in the file ends up written down the first column of the result, the second row is written down the second column, etc. The program is run by redirecting a file into the executable on the command -line; for instance, for the included 'info' file, the program +line; for instance, for the file 'info', the program would be run as follows: - schnitzi < info - +```sh +schnitzi < info +``` + The program generates interesting results when its source file is used as input: - + +```sh schnitzi < schnitzi.c - +``` + The result of this command is a program which does the exact same thing -- in other words, both the program and the "flipped" version of itself work identically (you'll need to redirect the diff --git a/1994/shapiro/README.md b/1994/shapiro/README.md index bc2c87662..7a445f164 100644 --- a/1994/shapiro/README.md +++ b/1994/shapiro/README.md @@ -1,24 +1,26 @@ # Most Well Rounded Obfuscation -Andrew T. Shapiro -CSES/CIRES University of Colorado -Campus Box 216 -Boulder, CO 80309-0216 -USA +Andrew T. Shapiro +CSES/CIRES University of Colorado +Campus Box 216 +Boulder, CO 80309-0216 +US ## To build: - make all +```sh +make all +``` [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed a bug on systems where `EOF != -1`. The problem is that `getc()` and the related functions do not return `-1` on EOF or error but rather `EOF`. However `EOF` is not required to be `-1` but merely an int < 0 and this program assumed that `getc()` will return -`-1` on EOF or error, not `EOF`. On systems where `EOF != -1` it could be a -problem. For the same reason one should not use `EOF` for the `getopt()` +`-1` on EOF or error, not `EOF`. On systems where `EOF != -1` it could result in +an infinite loop (for the same reason one should not use `EOF` for the `getopt()` functions as they return `-1` when all options are parsed (for details on the definition of `EOF` see `7.21 Input/output` subsection 1 of the -standard). An interesting problem occurred where changing the `-1` to `EOF` +standard)). An interesting problem occurred where changing the `-1` to `EOF` caused both `warning: illegal character encoding in string literal` and `error: source file is not valid UTF-8`. But since `EOF` is simply an int < 0 and making the loop condition check that the return value is >= 0 does not cause a @@ -28,7 +30,9 @@ assistance! ## To run: - ./shapiro & +```sh +./shapiro & +``` ## Try: @@ -86,7 +90,7 @@ obfuscation is a six member client/server hierarchy. (See the [shapiro.md](shapiro.md) file for a detailed description of the algorithm.) -Lint complains about: precedence confusion, `K` may be used before set, +`lint` complains about: precedence confusion, `K` may be used before set, main() returns random value to invocation environment, value type used inconsistently, value type declared inconsistently, function argument (number) used inconsistently, function returns value which is always diff --git a/1994/smr/README.md b/1994/smr/README.md index 8d805a73c..11a898eff 100644 --- a/1994/smr/README.md +++ b/1994/smr/README.md @@ -1,14 +1,16 @@ # Worst Abuse of the Rules -Szymon Rusinkiewicz -Massachusetts Institute of Technology -305 Memorial Dr., Room 005B -Cambridge, Ma 02139 -USA +Szymon Rusinkiewicz +Massachusetts Institute of Technology +305 Memorial Dr., Room 005B +Cambridge, Ma 02139 +US ## To build: - make all +```sh +make all +``` ## To run: @@ -36,10 +38,9 @@ compiler can't, the build instructions supplied with this entry will produce an executable file. On most systems, the stdout from the executable will exactly match original source. -In the future, the contest rules will specify a minimum size -that is one character larger than this entry, forever eliminating -this sort of program from contest. After all, how many variations -can one make on this entry? :-) +In the future, the contest rules will specify a minimum size that is one +character larger than this entry, forever eliminating this sort of program from +the contest. After all, how many variations can one make on this entry? :-) ## Author's remarks: diff --git a/1994/tvr/README.md b/1994/tvr/README.md index 9968ce946..6638de54c 100644 --- a/1994/tvr/README.md +++ b/1994/tvr/README.md @@ -1,14 +1,16 @@ # Best X11 Program -Teemu Rantanen -Helsinki University of Technology -Melkonkatu 5 A 8 -00210 Helsinki -Finland +Teemu Rantanen +Helsinki University of Technology +Melkonkatu 5 A 8 +00210 Helsinki +Finland ## To build: - make all +```sh +make all +``` ## To run: @@ -98,13 +100,13 @@ the fourth is a variation of that with more nice effects. The first parameter is the operating-mode of the program. There are 4 fractal -pairs, 3 display modes, making total of 12 modes. `Screensize` is half of the +pairs and 3 display modes, making total of 12 modes. `screensize` is half of the actual `screenlength/width`. I.e. if you use 128 as a second parameter, you will get two 256x256 windows. The program needs reasonable values for both of these parameters to -operate. A good first try could be "0 128" or "8 128". `Colormap` has -to be piped into the programs standard input. +operate. A good first try could be "0 128" or "8 128". The `colormap` has +to be redirected into the programs standard input via the `colormapfile`. Note that you will need approximately `(second_parameter^2)*64` bytes of free main memory or the machine will swap heavily (memory references are quite random @@ -112,23 +114,23 @@ and may confuse paging algorithms easily). This means that for 512x512 windows you will need 4M of memory. -### `Colormapfile`: +### `colormapfile` This is the file from which program reads colors for screen `colormap`. The first line of the file must be a number between `3..254`. This informs the program how many colors there are to be expected. This is also the maximum number of iterations used on picture calculations. Lines after that are X11 -color names. The program expects to find, and it uses, the number of colors +color names. The program expects to find, and will use, the number of colors reported on the first line. -There are two `colormapfiles` to start with. One with colors and another with +There are two `colormapfile`s to start with. One with colors and another with only black and white. If you have enough colors on your display you can use the one with colors (even on `grayscale`). The other is meant mainly for a one bit plane display (on which the picture looks terrible compared to a 8 bit plane display). -### Compilation: +### Compilation You should compile this entry with an optimizing compiler with the highest level of optimization possible. You will also need an ANSI @@ -157,6 +159,8 @@ between the X server and the client is slow. (Don't try this on 9600 bps modem line. I did ;) ) +### Obfuscation + Obfuscation is done on different levels. Almost none of it is made at the macro level, so `cpp`ing the code won't give you much. Perhaps most notable is the algorithmic obfuscation. Simple formula has been turned into something @@ -166,33 +170,36 @@ left out of the program because speed of animation was one of the key issues. Well, obfuscated or not, some of the effects are very nice ;) -### Memory refreshment: +### Memory refreshment Mandelbrot set is calculated from the formula +``` 2 Z = Z + Z n+1 n 0 - +``` and the Julian set is calculated from the formula +``` 2 Z = Z + C n+1 n +``` where `C` is the same throughout the picture. Both calculation are finished when `|Z| >= 2.0`. For the other fractals, the basic methods are the same but -the formula is different (look at the source ;) +the formula is different (look at the source ;) ) Note that Mandelbrot and Julian on this program aren't exactly correct. Find out why ;) -### Bugs: +### Bugs - No error checking. If DISPLAY is not set program dumps core. This may also happen if a request of some of the resources fails e.g. getting colors. diff --git a/1994/weisberg/README.md b/1994/weisberg/README.md index 384f030b8..9ab863d38 100644 --- a/1994/weisberg/README.md +++ b/1994/weisberg/README.md @@ -1,11 +1,11 @@ # Best Short Program -Jeff Weisberg -University of Rochester -Dept of Electrical Engineering -Computer Studies Bldg -Rochester, NY 14627 -USA +Jeff Weisberg +University of Rochester +Dept of Electrical Engineering +Computer Studies Bldg +Rochester, NY 14627 +US ## To build: @@ -43,7 +43,7 @@ it was read on stdin instead of via `cc -E`. ## Author's remarks: -### Description: +### Description The following short program implements the "Yet Another" algorithm for generating prime numbers. It will generate all primes up to 33554432, @@ -53,7 +53,7 @@ run to completion, so as an added feature, it will cease execution upon reception of a signal (any will do equally well), as well as in the event of a system shutdown or reboot. -### Bugs: +### Bugs The alternative version ([weisberg.alt](weisberg.alt.c)) has never actually run to completion. After running for close to a week it had reached somewhere around @@ -63,7 +63,7 @@ remarkably well). As there are quite a lot of primes to be found before reaching the output through your favorite pager (`more` or `less`), and not output to a paper output device (unless you have *LOTS* of paper). -### Technical: +### Technical The original "Yet Another Prime Program" algorithm used here was developed as a Computer Architecture course micro-programming exercise, and was designed to diff --git a/1994/westley/README.md b/1994/westley/README.md index 6326abd50..e7070bce9 100644 --- a/1994/westley/README.md +++ b/1994/westley/README.md @@ -1,11 +1,11 @@ # Worst Abuse of the C Preprocessor -Brian Westley (Merlyn LeRoy on Usenet) -Digi International -1906 James Ave. -St. Paul, MN 55105 -USA - +Brian Westley (Merlyn LeRoy on Usenet) +Digi International +1906 James Ave. +St. Paul, MN 55105 +US + ## To build: @@ -20,12 +20,8 @@ game! ## To run: -```sh -./westley -``` +There is no running as such. See below. -NOTE: your terminal should be set to 80 columns, 8 character tabs, and -wraparound. ## Try: @@ -38,6 +34,9 @@ cc -Describe -Door westley.c cc -Describe -Drain westley.c ``` +NOTE: your terminal should be set to 80 columns, 8 character tabs, and +wraparound. + ## Judges' remarks: Not all compiler errors are bad. diff --git a/1995/cdua/README.md b/1995/cdua/README.md index 5d5e93f89..81ba826fa 100644 --- a/1995/cdua/README.md +++ b/1995/cdua/README.md @@ -20,7 +20,7 @@ macOS which he also fixed. Thank you Cody for your assistance! NOTE: on modern systems this was hard to see it solve it in real time because it goes so quickly so Cody added an alternate version which makes it easier with modern systems to see the maze actually being solved in real time. We encourage -you to use this version but we keep the original here to both preserve the +you to use that version but we keep the original here to both preserve the original code (the bug fixes notwithstanding) and it will also let you see just how fast your computer is :-) (and you can also use both to see the difference). For this alternate, slower version, please see below. diff --git a/1995/dodsond1/README.md b/1995/dodsond1/README.md index c63ee45a1..76df83e1a 100644 --- a/1995/dodsond1/README.md +++ b/1995/dodsond1/README.md @@ -1,32 +1,39 @@ # Most Humorous - Don Dodson - AG Communication Systems - 4101 W Union Hills Dr #1104 - Glendale, AZ 85308 - USA +Don Dodson +AG Communication Systems +4101 W Union Hills Dr #1104 +Glendale, AZ 85308 +US ## To build: - make all +```sh +make all +``` ## To run: - ./dodsond1 < text_file +```sh +./dodsond1 < text_file +``` ## Try: - - ./dodsond1 < README.md +```sh +./dodsond1 < README.md +``` ## Judges' remarks: You might consider giving the following input: +``` ... a male (who) gets very, very frustrated sitting in a chair all the time because males are biologically driven to go out and hunt giraffes. -- Adjunct Professor Newt Gingrich, Reinhardt College, 1/7/95 +``` ... which can be done like: @@ -41,12 +48,12 @@ The obfuscation is on several levels. Most obviously, the shape of the program. -Underneath that, the variable names are in pig latin, as are the +Underneath that, the variable names are in pig Latin, as are the names of the standard C functions, such as putchar. Even main is -written as ainma. +written as `ainma`. The program construction is also very obfuscated, with all of the -code being inside the ()'s of one of the 6 "orfa" loops. +code being inside the ()'s of one of the 6 `orfa` loops. ## Copyright and CC BY-SA 4.0 License: diff --git a/1995/dodsond2/README.md b/1995/dodsond2/README.md index 2aaefd947..3cdde3163 100644 --- a/1995/dodsond2/README.md +++ b/1995/dodsond2/README.md @@ -1,19 +1,22 @@ # Best Game - Don Dodson - AG Communication Systems - 4101 W Union Hills Dr #1104 - Glendale, AZ 85308 - USA +Don Dodson +AG Communication Systems +4101 W Union Hills Dr #1104 +Glendale, AZ 85308 +US ## To build: - make all +```sh +make all +``` ## To run: - ./dodsond2 - +```sh +./dodsond2 +``` ## Judges' remarks: diff --git a/1995/esde/README.md b/1995/esde/README.md index b7cc7c73d..6ec517844 100644 --- a/1995/esde/README.md +++ b/1995/esde/README.md @@ -1,27 +1,32 @@ # Interesting Algorithm - Sebastian Deorowicz - ul. Radzionkowska 71a - 42-605 Tarnowskie Gory - Poland +Sebastian Deorowicz +ul. Radzionkowska 71a +42-605 Tarnowskie Gory +Poland ## To build: - make all +```sh +make all +``` ## To run: - ./esde data-file word +```sh +./esde data-file word +``` where data-file contains lines of < 255 chars in length. ## Try: - ./esde esde.data Johanson - ./esde esde.data2 read - ./esde README.md date - +```sh +./esde esde.data Johanson +./esde esde.data2 read +./esde README.md date +``` ## Judges' remarks: @@ -32,19 +37,19 @@ If you still don't know what it does, try [https://en.wikipedia.org/wiki/Soundex](https://en.wikipedia.org/wiki/Soundex). -## Author's remarks +## Author's remarks: -### what this program does: +### what this program does This program searches in the file words which have the same Soundex code -like the given word, and print out lines with these words. +of the given word, and print out lines with those words. -The Soundex code is using to find similar sounds words. +The Soundex code is used to find similar sounding words. Soundex code begins with the first letter of the word followed by a -three-digit code. There is the algorithm: +three-digit code. This is the algorithm: -0. Every letter in the word change by a digit (excluding the first letter). +0. Every letter in the word beyond the first letter is replaced by a digit. 1. Replace all pairs of the same code by single code (ex. R011235 -> R01235). 2. Remove all 0-codes (ex. R01235 -> R1235). 3. If length of code is > 4, get only first 4 codes (ex. R1235 -> R123). diff --git a/1995/garry/README.md b/1995/garry/README.md index 32d4a9e83..20b6aa329 100644 --- a/1995/garry/README.md +++ b/1995/garry/README.md @@ -56,35 +56,40 @@ the source called [garry.fmt.c](garry.fmt.c). ## Author's remarks: This program is a file filter, designed to do environment-expansion and -incorporating the ability to create binary from escaped data in the +incorporating the ability to create binary from escaped data in the environment variables. -The calling syntax is pretty simple, just use it with stdio-redirection +The calling syntax is pretty simple, just use it with stdio-redirection or inside pipelines, e.g.: - progname converted_file +```sh +./garry converted_file +``` or - cat all_my_files/* | progname | lp +```sh +cat all_my_files/* | ./garry | lp +``` -The syntax of the conversion of the input file is as follows: To include -the value of an environment variable in the output file, place the name -of the variable between "$"-signs in the input, e.g.: +The syntax of the conversion of the input file is as follows: To include the +value of an environment variable in the output file, place the name of the +variable between "$"-signs in the input, e.g.: My Home-Directory is: $HOME$ I'm using the path: $PATH$ -Unknown Env-variables or malformed expressions are ignored and kept -intact. +Unknown Env-variables or malformed expressions are ignored and kept intact. -Additionally, the filter replaces escaped octal values in the -environment variables by their binary representation, e.g.: +Additionally, the filter replaces escaped octal values in the environment +variables by their binary representation, e.g.: - $ TEST="\110\145\154\154\157" - $ export TEST - $ echo '$TEST$' | progname - Hello +```sh +$ TEST="\110\145\154\154\157" +$ export TEST +$ echo '$TEST$' | ./garry +Hello +``` ## Copyright and CC BY-SA 4.0 License: diff --git a/1995/heathbar/README.md b/1995/heathbar/README.md index af8d6b2a3..08e66d18c 100644 --- a/1995/heathbar/README.md +++ b/1995/heathbar/README.md @@ -1,24 +1,30 @@ # Best Layout - Heather Downs, Selene Makarios - The Software Bungalow - 900 High School Way, #2202 - Mountain View, CA 94041 - USA +Heather Downs & Selene Makarios +The Software Bungalow +900 High School Way, #2202 +Mountain View, CA 94041 +US ## To build: - make all +```sh +make all +``` ## To run: - ./heathbar num num +```sh +./heathbar num num +``` where num is a non-negative number. ## Try: - ./heathbar 4253 2281 +```sh +./heathbar 4253 2281 +``` ## Judges' remarks: @@ -29,7 +35,7 @@ effect of the source was self documenting! :-) ## Author's remarks Run this program with two non-negative integer arguments -(e.g. "prog 1234 999"). +(e.g. `./heathbar 1234 999`). My goal was to create the fastest possible C program. To that end, I made three critical observations: diff --git a/1995/leo/README.md b/1995/leo/README.md index 4d4e9778c..a5bf24f63 100644 --- a/1995/leo/README.md +++ b/1995/leo/README.md @@ -1,30 +1,37 @@ # Best Use of Obfuscation - Leonid A. Broukhis - 46728 Crawford St., apt. 20 - Fremont, CA 94539 - USA +Leonid A. Broukhis +46728 Crawford St., apt. 20 +Fremont, CA 94539 +US ## To build: - make all +```sh +make all +``` ## To run: - - ./leo [ deep ] [ right ] [ Variable ] [ cycle [ freq ] ] +```sh +./leo [ deep ] [ right ] [ Variable ] [ cycle [ freq ] ] +``` See the author's information below on these details. ## Try: - ./leo 1 | cat - /dev/tty | gs - +```sh +./leo 1 | cat - /dev/tty | gs - - ./leo 37 80 | cat - /dev/tty | gs - +./leo 37 80 | cat - /dev/tty | gs - +``` If you don't have gs or an equivalent postscript viewer, try: +```sh echo "" | ./leo 1 > foo.ps +``` and send foo.ps to your local postscript printer or open it in an appropriate application (e.g. GIMP). @@ -41,37 +48,39 @@ Some Ghostscripts/Postscript programs cleared the screen right after the image is drawn, so we added element 106 which acts as an input buffer. -To qualify for a category specially for yourself in the Geek code, -find out all the secret switches that the author doesn't divulge ! -(All switches are single characters on the command line - anything that's - not a number is a candidate) +To qualify for a category specially for yourself in the Geek code, find out all +the secret switches that the author doesn't divulge ! (All switches are single +characters on the command line - anything that's not a number is a candidate.) ## Author's remarks: The usage is: - ./leo [ deep ] [ right ] [ Variable ] [ cycle [ freq ] ] +```sh +./leo [ deep ] [ right ] [ Variable ] [ cycle [ freq ] ] +``` -where the first three are literal words, `cycle' is a positive -integer (0 is ignored), and `freq' is an integer (default = 0) -supposed to be in range 0..100 (bigger values are allowed, however). -Invalid parameters and options usually stop the command line -parsing (but not always, why?). The actual position of the word -options does not matter, so "prog.sh right Variable 1 70" -is equivalent to "prog.sh 0 0 0 1 Variable 70 right", etc. +where the first three are literal words, `cycle` is a positive integer (0 is +ignored), and `freq` is an integer (default = 0) that's supposed to be in the +range 0..100 (bigger values are allowed, however). Invalid parameters and +options usually stop the command line parsing (but not always, why?). The actual +position of the word options does not matter, so `./leo right Variable 1 70` is +equivalent to `./leo 0 0 0 1 Variable 70 right`, etc. If `Variable' is used, `cycle' is almost ignored (see below) but has to be present if you want to enter `freq' (and you usually do). Some options to try (besides the obvious): - ./leo 1 | cat - /dev/tty | gs - +```sh +./leo 1 | cat - /dev/tty | gs - +``` This draws the basic pattern I invented in high school: You take a big sheet of "arithmetic" paper and draw a line -of length 1 (between 2 crossings) it the center of the sheet: +of length 1 (between 2 crossings) at the center of the sheet: | @@ -79,23 +88,31 @@ This makes 2 open ends (I think the notion of an "open end" doesn't require explanations) in step 1. Now, until there are open ends in step N, repeat: for each open end pretend it points north and draw 2 lines going northwest and northeast from it to the nearest crossings. This needs to be -done "simultaneously" for all ends that are open at the moment. +done "simultaneously" for all ends that are open at that moment. Step 2: + +``` \./ | / \ +``` Step 3: + +``` __| |__ \./ | __ / \ __ | | +``` Step 4: + +``` . \./ \./ \__| |__/ @@ -104,9 +121,11 @@ Step 4: \__./ \.__/ / | | \ / \./ \ - +``` Step 5: + +``` ._| . |_. __| \./ \./ |__ \__| |__/ @@ -117,18 +136,21 @@ Step 5: |_./ \./ \._| | | -The lines marked by I show the places where "simultaneity" is significant. +``` -Note that so far all the drawings represent valid -structural formulas of some organic substances. +The lines marked by `I` show the places where "simultaneity" is significant. + +Note that so far all the drawings represent valid structural formulas of some +organic substances. step 1: ethane step 2: 2,3-dimethylbutane step 3: (2,5-dimethyl;3,4-isopropyl)-hexane step 4 and 5: I don't know. Do you? -etc. Step 6: + +``` \./ \./ \./ \./ ._| . |_. ._| . |_. \__| \./ \./ |__/ \__| \./ \./ |__/ @@ -140,13 +162,16 @@ Step 6: / |_./ \./ \._| / |_./ \./ \._| | | | | / \ / \ / \ / \ - + +``` + depending on the desired "hairiness". The original (paper-based) algorithm was "hairy", but it didn't look as good on the screen. The program cannot handle non-hairy mode 100% correctly - step 6 happens to be - + +``` |__ ...__/ ...__/ ... \ ... \. @@ -156,52 +181,66 @@ to be ...__/ ...__/ \ \.__ | - + +``` + and so on: the horisontal symmetry has been lost. That's why the opening for step 1 is not a single line but a cross: - + +``` \./ / \ +``` -To watch it repeatedly (as a screen saver), use: - - ./leo 2 | cat - /dev/tty | gs - +To watch it repeatedly (as a screensaver), use: + +```sh +./leo 2 | cat - /dev/tty | gs - +``` The command line: - ./leo Variable 1 | cat - /dev/tty | gs - +```sh +./leo Variable 1 | cat - /dev/tty | gs - +``` -This draws the same as above. Try: - - ./leo Variable 1 1 | cat - /dev/tty | gs - +draws the same as above. Try: -what happened to the picture? Increase `freq' and watch the changes. +```sh +./leo Variable 1 1 | cat - /dev/tty | gs - +``` -If `cycle' is more than 1, the program loops, allowing the user to -enjoy randomly changing patterns (the delay is 3 sec), -but there is a secret switch to suppress looping : useful +What happened to the picture? Increase `freq` and watch the changes. + +If `cycle` is more than 1, the program loops, allowing the user to +enjoy randomly changing patterns (the delay is 3 seconds), +but there is a secret switch to suppress looping: useful if you want to pipe the output to a printer. `uudecode` the spoiler below if you really want to know. +``` begin 664 spoiler1 M*%1H92!C;VQO;B J:7,J('1H92!S96-R970@ +US + ## To build: - make all +```sh +make all +``` ## To run: - ./schnitzi num +```sh +./schnitzi num +``` ## Try: - ./schnitzi 24 - ./schnitzi 18 - ./schnitzi 30 -NOTE: as the author warns do not use too high a number! If you wish to ignore +```sh +./schnitzi 24 +./schnitzi 18 +./schnitzi 30 +``` + +WARNING: the author warns to not use too high a number! If you wish to ignore the warning it is an exercise to determine how high is too high. :-) ## Judges' remarks: diff --git a/1995/spinellis/README.md b/1995/spinellis/README.md index 8c61c7794..7e0eb5aa2 100644 --- a/1995/spinellis/README.md +++ b/1995/spinellis/README.md @@ -1,27 +1,33 @@ # Abusing The Rules - Diomidis Spinellis - SENA S.A. - Kyprou 27 - GR-152 37 Filothei - Greece +Diomidis Spinellis +SENA S.A. +Kyprou 27 +GR-152 37 Filothei +Greece + ## To build: - make all +```sh +make all +``` ## To run: - ./spinellis < spinellis.c +```sh +./spinellis < spinellis.c +``` -## Judges' remarks +## Judges' remarks: While the code does not abuse the rules, its output surely does! P.S. Does the source have any spelling errors? -## Author's remarks + +## Author's remarks: 96% of the program lines (631 out of the 658) are comment text rendering the program readable and understandable. With the exception of the diff --git a/1995/vanschnitz/README.md b/1995/vanschnitz/README.md index 6180eef8d..18b9d75b4 100644 --- a/1995/vanschnitz/README.md +++ b/1995/vanschnitz/README.md @@ -1,24 +1,38 @@ # Worst Abuse of the C Preprocessor and Most Likely To Amaze - Mark Schnitzius & David Van Brackle - ISX Corporation - 1165 Northchase Parkway - Suite 120 - Marietta, GA 30067 - USA +Mark Schnitzius & David Van Brackle +ISX Corporation +1165 Northchase Parkway +Suite 120 +Marietta, GA 30067 +US ## To build: - make all +```sh +make all +``` ## To run: - ./vanschnitz +```sh +./vanschnitz +``` ## Try: - make clobber all LEVEL=6 - ./vanschnitz +```sh +make clobber all LEVEL=6 +./vanschnitz +``` + +### Alternate code: + +The authors provided a spoiler version of the program. Originally uuencoded we +have decoded it for the wider audience in [spoiler.c](spoiler.c). The +`uuencode`d blob is still available in their remarks below. They encourage you +to first try and figure it out without it. + ## Judges' remarks: @@ -44,30 +58,32 @@ solution. How do you trick a compiler into actually solving the problem? First, you must tell it how many disks you wish to solve it -for. This is done by defining the symbol 'n' on the compile +for. This is done by defining the symbol `n` on the compile line. For instance, to cause the compiler to solve the Towers of Hanoi problem with four disks, you would compile the program like this: - gcc hanoi.c -o hanoi -Dn=4 +```sh +gcc hanoi.c -o hanoi -Dn=4 +``` -A default value of 5 will be used for n if you do not define -it on the command line. The value of n cannot be greater than +A default value of `5` will be used for `n` if you do not define +it on the command line. The value of `n` cannot be greater than fifteen (the compiler we used to test has a limit on the #include depth). The compiler then solves the problem using binary arithmetic based on whether particular symbols are defined or not. -To loop, the program #include's itself. This is, of course, -expensive; one compile we did with n=14 took about fifty -minutes to compile on our system (compiling with n=15 -caused our system to crash). +To loop, the program `#include`s itself. This is, of course, +expensive; one compile we did with `n=14` took about fifty +minutes to compile on our system (compiling with `n=15` caused our system to +crash). The resulting program that the compiler generates simply prints out the answer. Did I say "simply"? Actually, the whole resulting program consists of a single printf statement, consisting of a massive string constant of length `35*(2^n-1)`, followed by `3*(2^n-1)` integers which get formatted into the -string. For our n=14 run, this adds up to a string constant +string. For our `n=14` run, this adds up to a string constant of length 573405, followed by 49149 integers delimited by commas. (Generating the string constant depends on the ANSI C feature in which adjacent character strings are @@ -75,14 +91,16 @@ catenated; a version that does not use this feature has been included for people who can only run K&R). A good way to see the resulting program (on a Unix system) is to do the command - gcc hanoi.c -E -Dn=5 | grep -v \# | grep -v ^\$ +```sh +gcc hanoi.c -E -Dn=5 | grep -v \# | grep -v ^\$ +``` For an odd number of disks, the program will provide a solution wherein the disks end up on peg 2; for an even number of disks, they will end on peg 3. This should provide some hint as to what sort of algorithm is used. -We have included a "spoiler" version of the program, with +We have included a [spoiler](spoiler.c) version of the program, with meaningful symbol names and comments, but we encourage you to try to decipher the program without it... diff --git a/1995/vanschnitz/spoiler.c b/1995/vanschnitz/spoiler.c new file mode 100644 index 000000000..d22d60cd5 --- /dev/null +++ b/1995/vanschnitz/spoiler.c @@ -0,0 +1,239 @@ +#ifndef INITIALIZED + +/* + * If n isn't defined, make it 5 + */ +#ifndef n +#define n 05 +#endif + +/* + * Some useful variables + */ +#define THIS_FILE __FILE__ +#define FORMAT_STRING "Move disk %d from peg %d to peg %d\n" +#define INITIALIZED + +/* + * Translate n into bits + */ +#if n&01 +#define bit0 +#endif +#if n&02 +#define bit1 +#endif +#if n&04 +#define bit2 +#endif +#if n>>3 +#define bit3 +#endif + +/* + * Here's the program! + */ +main(){ +printf( +#include THIS_FILE +#define NOW_DO_THE_NUMBERS +#include THIS_FILE +);} + +#else + +/* + * Check to see if the number is zero (bottom of recursion) + */ +#ifdef bit0 +#define N_IS_NOT_ZERO +#endif +#ifdef bit1 +#define N_IS_NOT_ZERO +#endif +#ifdef bit2 +#define N_IS_NOT_ZERO +#endif +#ifdef bit3 +#define N_IS_NOT_ZERO +#endif + +#ifdef N_IS_NOT_ZERO +#undef N_IS_NOT_ZERO + +/* + * Decrement n + */ +#ifndef bit0 +#define bit0 +#ifndef bit1 +#define bit1 +#ifndef bit2 +#define bit2 +#ifndef bit3 +#define bit3 +#else +#undef bit3 +#endif +#else +#undef bit2 +#endif +#else +#undef bit1 +#endif +#else +#undef bit0 +#endif + +/* + * Here's recursion + */ +#include THIS_FILE + +/* + * Note: Odd numbered disks always cycle from 1 => 2 => 3 => 1 => 2 => 3 + * Even numbered disks always cycle from 1 => 3 => 2 => 1 => 3 => 2 + */ + +/* + * Check to see if n is zero. If so, we're moving disk 1. + * In general, for any n we're moving disk n+1. That means that + * when n is odd, we're moving an even disk, and vice versa. + */ +#ifndef bit0 +#ifndef bit1 +#ifndef bit2 +#ifndef bit3 +#define N_IS_ZERO +#endif +#endif +#endif +#endif + +#ifdef N_IS_ZERO +#undef N_IS_ZERO + +#ifndef NOW_DO_THE_NUMBERS +FORMAT_STRING +#else + +/* + * If disk 1 is on peg 2, move it 2 => 3 + */ +#ifdef DISK_ONE_IS_ON_PEG_TWO +,1,2,3 +#undef DISK_ONE_IS_ON_PEG_TWO +#define DISK_ONE_IS_ON_PEG_THREE +#else + +/* + * If disk 1 is on peg 3, move it 3 => 1 + */ +#ifdef DISK_ONE_IS_ON_PEG_THREE +,1,3,1 +#undef DISK_ONE_IS_ON_PEG_THREE +#else + +/* + * Disk 1 must be on peg 1. Move it 1 => 2 + */ +,1,1,2 +#define DISK_ONE_IS_ON_PEG_TWO +#endif +#endif +#endif +#else + +/* + * Here, we handle disks >1. Remember that odds cycle 1 => 2 => 3 => 1, + * and evens cycle 1 => 2 => 3 => 1. Combine this with the knowledge + * of where disk 1 is, and we can determine how to move any disk. + */ +#ifndef NOW_DO_THE_NUMBERS +FORMAT_STRING +#else + +/* + * Print the disk number. Remember, disk number = n+1 + */ +,1 +#ifdef bit0 ++1 +#endif +#ifdef bit1 ++2 +#endif +#ifdef bit2 ++4 +#endif +#ifdef bit3 ++8 +#endif + +/* + * Disk 1 on peg 2 + */ +#ifdef DISK_ONE_IS_ON_PEG_TWO +#ifdef bit0 +,1,3 /* Even: 1 => 3 (n is odd, so the disk is even) */ +#else +,3,1 /* Odd: 3 => 1 */ +#endif +#else + +/* + * Disk 1 on peg 3 + */ +#ifdef DISK_ONE_IS_ON_PEG_THREE +#ifdef bit0 +,2,1 /* Even: 2 => 1 */ +#else +,1,2 /* Odd: 1 => 2 */ +#endif +#else + +/* + * Disk 1 on peg 1 + */ +#ifdef bit0 +,3,2 /* Even: 3 => 2 */ +#else +,2,3 /* Odd: 2 => 3 */ +#endif +#endif +#endif +#endif +#endif + +/* + * More recursion + */ +#include THIS_FILE + +/* + * Increment n + */ +#ifdef bit0 +#undef bit0 +#ifdef bit1 +#undef bit1 +#ifdef bit2 +#undef bit2 +#ifdef bit3 +#undef bit3 +#else +#define bit3 +#endif +#else +#define bit2 +#endif +#else +#define bit1 +#endif +#else +#define bit0 +#endif + +#endif /* #ifdef N_IS_NOT_ZERO */ + +#endif /* #else of #ifndef INITIALIZED */ diff --git a/1996/README.md b/1996/README.md index c128016c3..370af3293 100644 --- a/1996/README.md +++ b/1996/README.md @@ -72,7 +72,7 @@ contest have not been formed at this time and are not expected to be ready for distribution until late February 1998. So what happened to 1997? Well the next USENIX Technical Conference -will be held Jun 15-19, 1998 (in New Orleans, USA). The 18 month +will be held Jun 15-19, 1998 (in New Orleans, US). The 18 month span between conferences will cause the IOCCC to skip over 1997. Be sure to wait until the 1998 rules are posted before submitting entries. diff --git a/1996/august/.gitignore b/1996/august/.gitignore index 9ea775773..0b5694ffe 100644 --- a/1996/august/.gitignore +++ b/1996/august/.gitignore @@ -1,3 +1,8 @@ august august.oc test.oo +fac.oo +parse.oo +prog.oc +august.oo +prog.oo diff --git a/1996/august/Makefile b/1996/august/Makefile index eac9f9e19..3200372aa 100644 --- a/1996/august/Makefile +++ b/1996/august/Makefile @@ -38,7 +38,7 @@ include ../../var.mk # Common C compiler warnings to silence # -CSILENCE= -Wno-error -Wno-implicit-function-declaration -Wno-invalid-source-encoding +CSILENCE= -Wno-error -Wno-implicit-function-declaration -Wno-invalid-source-encoding -Wno-invalid-utf8 # Common C compiler warning flags # @@ -57,7 +57,7 @@ ARCH= # Defines that are needed to compile # -CDEFINE= -DZ=60000 -D'T=m[s]' -D'P=m[s++]' \ +CDEFINE= -DZ=240000 -D'T=m[s]' -D'P=m[s++]' \ -D'L=m[p++]' -D'g=getchar()' -DE=else -DW=while -D'B=m[p++]' \ -DI=if -DR='s=s+l/2;T=r;I(l%2)s++' -D'X=m[s-' \ -D'D=Q(13,-)Q(14,*)Q(15,/)Q(16,%)Q(6,==)Q(7,!=)Q(8,<)C(1,r=P;m[T]=r;T=r)C(9,r=P;m[T]=r;s++)' diff --git a/1996/august/README.md b/1996/august/README.md index 16b021297..6185a6e36 100644 --- a/1996/august/README.md +++ b/1996/august/README.md @@ -1,65 +1,100 @@ # Best of Show - Lennart Augustsson - CR&T - Stora Badhusgatan 18-20 - S-411 21 Goteborg - Sweden +Lennart Augustsson + + ## To build: - make all +```sh +make all +``` ## To run: - cat august.c test.oc | ./august > test.oo - ./august < test.oo +```sh +cat august.c test.oc | ./august > test.oo +./august < test.oo +``` - NOTE: Some compilers will compile this code into infinite loops! - If the above cat line does not execute in a very short amount - of time, then you may need to fix your compiler or use gcc. + +NOTE: Some compilers like clang will compile this code into infinite loops! If +the above cat line (or one of the ones later in the try section) does not +execute in a very short amount of time, then you may need to fix your compiler +or use gcc. + +The above should print a `!` followed by a newline. + +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed a segfault in +this program that prevented it from working right but he notes it hangs in +macOS. It works fine in linux. This is because macOS has clang, not gcc, even +the gcc binary. He observed that with specific compiler flags it hangs in linux +too and perhaps it's related to this in macOS; maybe other flags are needed but +he doesn't know (at least not yet). He provided a bit more information in +[bugs.md](/bugs.md) for anyone who wants to have a go at providing a fix for +other compilers. As there are a lot of commands to try he also added +[try.sh](try.sh). Thank you Cody for your assistance! ## Try: - cat august.c fac.oc | ./august > fac.oo - ./august < fac.oo +```sh +cat august.c fac.oc | ./august > fac.oo +./august < fac.oo - cat august.c fac.oc | ./august | ./august +cat august.c fac.oc | ./august | ./august - cat august.c parse.oc | ./august > parse.oo - cat parse.oo fac.oc | ./august | ./august +cat august.c parse.oc | ./august > parse.oo +cat parse.oo fac.oc | ./august | ./august +``` ## Judges' remarks: -This entry can feed on itself. If you C preprocess the source, +This entry can feed on itself. If you C pre-process the source, you compile the interpreter: - make august.oc +```sh +make august.oc +``` We can now compile the interpreter as follows: - cat august.c august.oc | ./august > august.oo +```sh +cat august.c august.oc | ./august > august.oo +``` and use the compiled interpreter to execute some previously compiled code: - cat august.oo test.oo | ./august +```sh +cat august.oo test.oo | ./august +``` And we can have the compiled interpreter interpret itself which in turn compiles the test program: - cat august.oo august.oo fac.oo | ./august +```sh +cat august.oo august.oo fac.oo | ./august +``` And if you have lots of spare time, you can recurse one level deeper: - cat august.oo august.oo august.oo fac.oo | ./august +```sh +cat august.oo august.oo august.oo fac.oo | ./august +``` + +NOTE: to run all the commands in the above sections you can also use the +[try.sh](try.sh) script like: + +```sh +./try.sh +``` We (the judges) recommend that you spend some time studying this entry as it surely will make the 'best of the IOCCC' list. It was very well received by those who attended the IOCCC BOF. -## Author's remarks +## Author's remarks: This program is a bytecode interpreter. This fact is not particularly obfuscated; any experienced C programmer can see that @@ -86,70 +121,88 @@ The compiler has absolutely no error checking, so things can go wrong. But this is what seasoned C programmers are used to. Assume that the interpreter has been compiled (source in prog.c and -binary in prog) and that we have this in a file named test.oc: +binary in prog) and that we have this in a file named `test.oc`: - main() { putchar('!'); putchar('\n'); exit(0); } +``` +main() { putchar('!'); putchar('\n'); exit(0); } +``` We can then compile by - cat august.c test.oc | ./august > test.oo +```sh +cat august.c test.oc | ./august > test.oo +``` And run the compiled program by - ./august < test.oo +```sh +./august < test.oo +``` Or even simpler: - cat august.c test.oc | ./august | ./august - -A larger example is included fac.oc. +```sh +cat august.c test.oc | ./august | ./august +``` -The compiler for OC is naturally written in OC (where did you think -the byte code came from?). It is in the file parse.oc. +A larger example is included [fac.oc](fac.oc). -Hmm... So now we have an interpreter written in OC and a compiler -for OC, can we compile the interpreter? Yes, we can! The OC -compiler does not have a preprocessor (hey, what do you expect from -a program that is this small), so we need to use an external one. -To preprocess august.c use the command from the build file, but add -the -E flag and change 60000 to 40000, i.e.: +The compiler for OC is naturally written in OC (where did you think the byte +code came from?). It is in the file [parse.oc](parse.oc). - cc -E -DZ=40000 .... august.c > prog.oc +Hmm... So now we have an interpreter written in OC and a compiler for OC, can +we compile the interpreter? Yes, we can! The OC compiler does not have a +preprocessor (hey, what do you expect from a program that is this small), so we +need to use an external one. To pre-process [august.c](august.c) use the +command from the Makefile, but add the `-E` flag and change 60000 to 40000, +i.e.: -If prog.oc contain some junk line starting with a `#' (most likely +```sh +cc -E -DZ=40000 .... august.c > prog.oc +``` + +If `prog.oc` contain some junk line starting with a `#' (most likely it does) then remove it. OK, we can now compile the interpreter: - cat august.c prog.oc | ./august > prog.oo +```sh +cat august.c prog.oc | ./august > prog.oo +``` And we can run it: - cat prog.oo test.oo | ./august +```sh +cat prog.oo test.oo | ./august +``` Here we have the interpreter interpreting another interpreter that runs the program. Did you think that was too fast? Just throw in another level of interpretation: - cat prog.oo prog.oo test.oo | ./august +```sh +cat prog.oo prog.oo test.oo | ./august +``` And another... - cat prog.oo prog.oo prog.oo test.oo | ./august +```sh +cat prog.oo prog.oo prog.oo test.oo | ./august +``` -***** +--- Fitting the byte code for the compiler into the initial comment was a challenge. I had to strip the compiler/interpreter of a lot of functionality to bring down their sizes. The initial -version had a full set of binary operators as well as prefix &. +version had a full set of binary operators as well as prefix `&`. Given a handful more bytes it would be easy to put them back. Anyway, the bytecode from the compiler is first optimized in an external optimizer (not supplied here); this brings down the size of it by about 30%. The remaining code is then LZ-compressed (roughly) with a sliding window of 255 bytes. The most common -occuring bytes are then encoded using " \n\t;{}" to avoid having +occuring bytes are then encoded using `" \n\t;{}"` to avoid having them counted as significant. About 200 bytes of the interpreter handles the unpacking of the byte code (this is a lot, but it pays off). @@ -161,75 +214,77 @@ coder), but decompression then takes up too much code. Maybe this would be a way to fit it all into the 1536 bytes, but I'm don't have time to try it. -***** +--- -Execution starts at main(). Nothing can be used before it is -defined. getchar() and putchar() are predefined functions. +Execution starts at `main()`. Nothing can be used before it is +defined. `getchar()` and `putchar()` are predefined functions. -The following is a description of the OC grammar: +Below is a description of the OC grammar. -OC grammar -========== +### OC grammar -Terminals are in quotes, () is used for bracketing. +Terminals are in quotes, `()` is used for bracketing. - program: decl* +``` +program: decl* - decl: vardecl - fundecl +decl: vardecl + fundecl - vardecl: type NAME ; - type NAME "[" INT "]" ; +vardecl: type NAME ; + type NAME "[" INT "]" ; - fundecl: type NAME "(" args ")" "{" body "}" +fundecl: type NAME "(" args ")" "{" body "}" - args: /*empty*/ - ( arg "," )* arg +args: /*empty*/ + ( arg "," )* arg - arg: type NAME +arg: type NAME - body: vardecl* stmt* +body: vardecl* stmt* - stmt: ifstmt - whilestmt - dowhilestmt - "return" expr ";" - expr ";" - "{" stmt* "}" - ";" +stmt: ifstmt + whilestmt + dowhilestmt + "return" expr ";" + expr ";" + "{" stmt* "}" + ";" - ifstmt: "if" "(" expr ")" stmt - "if" "(" expr ")" stmt "else" stmt +ifstmt: "if" "(" expr ")" stmt + "if" "(" expr ")" stmt "else" stmt - whilestmt: "while" "(" expr ")" stmt +whilestmt: "while" "(" expr ")" stmt - dowhilestmt: "do" stmt "while" "(" expr ")" ";" +dowhilestmt: "do" stmt "while" "(" expr ")" ";" - expr: expr binop expr - unop expr - expr "[" expr "]" - "(" expr ")" - expr "(" exprs ")" - NAME - INT - CHAR - STRING +expr: expr binop expr + unop expr + expr "[" expr "]" + "(" expr ")" + expr "(" exprs ")" + NAME + INT + CHAR + STRING - exprs: /*empty*/ - (expr ",")* expr +exprs: /*empty*/ + (expr ",")* expr - binop: "+" | "-" | "*" | "/" | "%" | - "=" | - "<" | "==" | "!=" +binop: "+" | "-" | "*" | "/" | "%" | + "=" | + "<" | "==" | "!=" - unop: "!" | "-" | "*" +unop: "!" | "-" | "*" - type: "int" stars - "char" stars +type: "int" stars + "char" stars - stars: "*"* +stars: "*"* -***** +``` + +--- Well, that is enough ranting for now. diff --git a/1996/august/try.sh b/1996/august/try.sh new file mode 100755 index 000000000..58c968a75 --- /dev/null +++ b/1996/august/try.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +make clobber all +set -x +cat august.c test.oc | ./august > test.oo +./august < test.oo +cat august.c fac.oc | ./august > fac.oo +./august < fac.oo + +cat august.c fac.oc | ./august | ./august + +cat august.c parse.oc | ./august > parse.oo +cat parse.oo fac.oc | ./august | ./august + +rm august.oc +make august.oc +cat august.c august.oc | ./august > august.oo +cat august.oo test.oo | ./august +cat august.oo august.oo fac.oo | ./august +cat august.oo august.oo august.oo fac.oo | ./august diff --git a/1996/dalbec/README.md b/1996/dalbec/README.md index 86f67d5b6..3dbccd6cf 100644 --- a/1996/dalbec/README.md +++ b/1996/dalbec/README.md @@ -1,16 +1,16 @@ # Best Numerical Obfuscation - John Dalbec - 20 Squire's Ct. (home address) - Canfield, OH 44406 - USA - - http://www.math.yale.edu/pub/users/dalbec/ +John Dalbec +20 Squire's Ct. (home address) +Canfield, OH 44406 +US + ## To build: - make all - +```sh +make all +``` [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) proposed a fix for this to compile with clang and Landon implemented it after some discussion. The @@ -27,12 +27,15 @@ thanks to Yusuke for confirming the output is correct! ## To run: - ./dalbec +```sh +./dalbec +``` ## Try: - - ./dalbec 3 | head -n 29 +```sh +./dalbec 3 | head -n 29 +``` Why does the output end with 121? @@ -65,25 +68,26 @@ space is roughly proportional to the last number printed. (On SunOS/cc, the proportionality constant is about 48 bytes.) On completion, the program produces a core file that may be used to -refine this estimate. (Or you could try typing "limit" if you're -running `csh`.) In rare cases the stack space may exceed `24*MAXINT` +refine this estimate. (Or you could try typing `limit` if you're +running `csh`.) In rare cases the stack space may exceed `24*INT_MAX` bytes, in which case the program will produce an inaccurate estimate. -This program is obfuscated: +This program is obfuscated by: -1. by the use of easily-confused variable names +1. The use of easily-confused variable names. -2. by using the implicit !=0 in conditional expressions +2. Using the implicit `!=0` in conditional expressions. -3. by substituting expressions such as !a for 0 where a!=0 and !a for 1 where a==0 +3. Substituting expressions such as `!a` for `0` where `a!=0` and `!a` for `1` +where `a==0`. -4. by the fact that main() is a single expression and so beautifies poorly +4. The fact that `main()` is a single expression and so beautifies poorly. -5. by the fact that main() is used +5. The fact that `main()` is used: - - to compute powers in modular arithmetic + - to compute powers in modular arithmetic. - - to recursively call itself in the main loop + - to recursively call itself in the main loop. ## Copyright and CC BY-SA 4.0 License: diff --git a/1996/eldby/.gitignore b/1996/eldby/.gitignore index 6fffc035b..e3f55ca6d 100644 --- a/1996/eldby/.gitignore +++ b/1996/eldby/.gitignore @@ -1 +1,2 @@ eldby +eldby.alt diff --git a/1996/eldby/Makefile b/1996/eldby/Makefile index 9bdeef389..a6d42c6ed 100644 --- a/1996/eldby/Makefile +++ b/1996/eldby/Makefile @@ -58,7 +58,7 @@ ARCH= # Defines that are needed to compile # -CDEFINE= +CDEFINE= -DZ=35000 # Include files that are needed to compile # @@ -114,8 +114,8 @@ OBJ= ${PROG}.o DATA= TARGET= ${PROG} # -ALT_OBJ= -ALT_TARGET= +ALT_OBJ= ${PROG}.alt.o +ALT_TARGET= ${PROG}.alt ################# diff --git a/1996/eldby/README.md b/1996/eldby/README.md index b51756a9d..6e6a4b5df 100644 --- a/1996/eldby/README.md +++ b/1996/eldby/README.md @@ -1,29 +1,54 @@ # Best Output - Thor AAge Eldby - European Technology Partner - Roedtvetvn 20 (Home address) - 0955 OSLO - Norway +Thor AAge Eldby +European Technology Partner +Roedtvetvn 20 (Home address) +0955 Oslo +Norway ## To build: - make all +```sh +make all +``` -## To run +## To run: - ./eldby +```sh +./eldby +``` WARNING: on modern systems this is very fast and could be a problem for those susceptible to photosensitivity. Please try this one with caution if this -applies to you! The same goes for people who can be overstimulated. +applies to you! The same goes for people who can be overstimulated. See below +for alternate version if you want to see it go slower or if seeing things move +by too fast is a problem for you. -## Judges' remarks +NOTE: to reset the sanity of your terminal after this program ends try `reset`. + + +### Alternate code: + +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) provided an alternate +version which uses `usleep()` in between writing the output for those who are +sensitive to text flashing by rapidly (it affects him too but he also thinks it +moves too fast nowadays anyway). The default sleep duration is `35000` but you can +change it at compilation like: + +```sh +make CFLAGS+="-DZ=20000" clobber alt +``` + +Use `eldby.alt` as you would `eldby`. + +Thank you Cody! + +## Judges' remarks: We were impressed by the author's ability to render spheres in 3D in a very small chunk of code. -## Author's remarks +## Author's remarks: This program shows flying spheres. The program eats CPU on lesser equipped systems. The program will run until termination. Terminal diff --git a/1996/eldby/eldby.alt.c b/1996/eldby/eldby.alt.c new file mode 100644 index 000000000..fc4c02289 --- /dev/null +++ b/1996/eldby/eldby.alt.c @@ -0,0 +1,10 @@ +#include +#include +float s=1944,x[5],y[5],z[5],r[5],j,h,a,b,d,e;int i=33,c,l,f=1;int g(){return f= +(f*6478+1)%65346;}m(){x[i]=g()-l;y[i]=(g()-l)/4;r[i]=g()>>4;}main(){char t[1948 +]=" `MYmtw%FFlj%Jqig~%`jqig~Etsqnsj3stb",*p=t+3,*k="3tjlq9TX";l=s*20;while(i0) +{for(e=b;e*e>b*1.01||e*e - huffmancoding@gmail.com +Ken Huffman +Applied Innovation Inc +5800 Innovation Dr. +Dublin, OH 43016 +US + +huffmancoding@gmail.com ## To build: - make all +```sh +make all +``` ## To run: - - echo 'Huffman Decoding' | ./huffman +```sh +echo 'Huffman Decoding' | ./huffman +``` NOTE: this program uses `gets()` so you will likely get a warning when compiling and/or running on modern systems. ## Try: - echo 'seeing or feeling is believing' | ./huffman - echo 'CC OR NOT CC' | ./huffman | ./huffman +```sh +echo 'seeing or feeling is believing' | ./huffman +echo 'CC OR NOT CC' | ./huffman +echo 'CC OR NOT CC' | ./huffman | ./huffman +``` ## Judges' remarks: @@ -35,7 +41,9 @@ And for a misleading hint, consider who won! :-) And if you really can't see what is going on, here is an extra spoiler: - ./huffman < huffman.c +```sh +./huffman < huffman.c +``` This entry was very well received at the IOCCC BOF. @@ -45,7 +53,7 @@ This filter program is really not obfuscated code. It compiles cleanly with an ANSI C compiler and comes with user documentation that even a blind person could read. -The program is a bi-directional filter with the output of the program +The program is a bidirectional filter with the output of the program suitable for its input. The output of this program, when used as input, undoes the original program filtering. diff --git a/1996/jonth/README.md b/1996/jonth/README.md index 744e3908c..75fabacd7 100644 --- a/1996/jonth/README.md +++ b/1996/jonth/README.md @@ -1,45 +1,57 @@ # Best X11 Entry - Jon Thingvold - University of Oslo - Gaustadveien 10B - N 0372 Oslo - Norway - - http://www.uio.no/~jonth/ +Jon Thingvold +University of Oslo +Gaustadveien 10B +N 0372 Oslo +Norway +http://www.uio.no/~jonth/ ## To build: - make all +```sh +make all +``` + +NOTE: this entry requires `X11/Xlib.h` header file and the X11 library to +compile. macOS users running Mountain Lion and later will need to download and +install [XQuartz](https://www.xquartz.org) in order to compile and run this +entry. But see [bugs.md](/bugs.md) for a known problem with running this under +macOS and with a workaround of sorts plus more information on where it fails. + ## To run: - ./jonth +```sh +./jonth :0 :0 +``` ## Try: - ./jonth host1:0 host2:0 +```sh +./jonth host1:0 host2:0 +``` ## Judges' remarks: -For extra credit, figure out how you can cheat by taking over -a square already occupied by an opponent. +For extra credit, figure out how you can cheat by taking over a square already +occupied by an opponent. ## Author's remarks: -This is multi-user tic-tac-toe for X Windows. You may give one or two X -displays as arguments to this game. +This is multi-user tic-tac-toe for X Windows. You may give one or two X displays +as arguments to this game. ### Known bugs: -Sometimes on Solaris X gets confused and this program core dumps, -solution: give two display arguments (prog host:0 host:0) +Sometimes on Solaris X gets confused and this program core dumps. The solution: +give two display arguments (`./jonth host:0 host:0`). -If one (or both) windows look like a copy of the window(s) below, -try xrefresh command. +If one (or both) windows look like a copy of the window(s) below, try +`xrefresh(1)` command. -Have a nice(1) day. +Have a `nice(1)` day. ## Copyright and CC BY-SA 4.0 License: diff --git a/1996/rcm/README.md b/1996/rcm/README.md index 4edcecc29..648505a01 100644 --- a/1996/rcm/README.md +++ b/1996/rcm/README.md @@ -1,37 +1,45 @@ # Best RFC Obfuscation - Ron McFarland - 7941 Fawncreek Drive - Cincinnati, Ohio 45249 - USA +Ron McFarland +7941 Fawncreek Drive +Cincinnati, Ohio 45249 +US ## To build: - make all +```sh +make all +``` ## To run: - ./rcm < rfc1951.gz +```sh +./rcm < rfc1951.gz +``` ## Try: For more information try: - ./rcm < rfc1952.gz - +```sh +./rcm < rfc1952.gz +``` ## Judges' remarks: For a good noop try: - gzip -c < rcm.c | ./rcm +```sh +gzip -c < rcm.c | ./rcm +``` ## Author's remarks: -Except for some silly requirements regarding input validation, CRC -checking, and similar unimportant fluff, this program is a fully -compliant RFC1951/RFC1952 (GNU Gzip) file uncompressor. Feed it a -"gzip" compressed file on standard input, and it will write the fully +Except for some silly requirements regarding input validation, CRC checking, and +similar unimportant fluff, this program is a fully compliant +[RFC1951](https://www.ietf.org/rfc/rfc1951.txt)/[RFC1952](https://www.ietf.org/rfc/rfc1952.txt) +([GNU Gzip](https://www.gnu.org/software/gzip/)) file uncompressor. Feed it a +`gzip` compressed file on standard input, and it will write the fully uncompressed original file to standard output. ### ObJustifications for this entry: @@ -39,7 +47,7 @@ uncompressed original file to standard output. #### The Design Trade-off Argument: "The 184 characters worth of defines in the build file have been -carefully offset by 184 redundant and unnecessary '{', '}', and ';' +carefully offset by 184 redundant and unnecessary '`{`', '`}`', and '`;`' characters in the source file." #### The Design Review Argument: @@ -49,12 +57,12 @@ meets and actually exceeds specification." #### The Program Metrics Argument: -"The program source is less than 3,100 characters in length and -uncompresses file `emacs-19.34b.tar.gz' in about 130 seconds on -my HP 9000/735. The now obsolete source file `inflate.c' from -the GNU gzip source tree is 31,613 characters in length and -uncompresses the emacs distribution file in slightly under 25 -seconds. Thus: +"The program source is less than 3,100 characters in length and uncompresses +file +[emacs-19.34b.tar.gz](https://ftp.gnu.org/old-gnu/emacs/emacs-19.34b.tar.gz) in +about 130 seconds on my HP 9000/735. The now obsolete source file `inflate.c' +from the GNU gzip source tree is 31,613 characters in length and uncompresses +the emacs distribution file in slightly under 25 seconds. Thus: 3100 / 130 = 23.85 -vs- 31613 / 25 = 1264.52 diff --git a/1996/schweikh1/README.md b/1996/schweikh1/README.md index 115dd52df..3a325ce9c 100644 --- a/1996/schweikh1/README.md +++ b/1996/schweikh1/README.md @@ -1,20 +1,32 @@ # Worst Abuse of the C Preprocessor - Jens Schweikhardt - DFN Network Operation Center - Schlartaeckerweg 3 (home address) - D-71384 Weinstadt - Germany - - http://www.uni-stuttgart.de/People/schweikhardt/home.html +Jens Schweikhardt +DFN Network Operation Center +Schlartaeckerweg 3 (home address) +D-71384 Weinstadt +Germany + ## To build: - make all +```sh +make all +``` ## To run: - ./schweikh1 +```sh +./schweikh1 +``` + +## Try: + +To find the day that Easter falls on in the current year: + +```sh +./schweikh1 |grep $(date +%Y) +``` + ## Judges' remarks: @@ -27,18 +39,18 @@ C Preprocessor that the judges have seen this year! ## Author's remarks: -What this program does ----------------------- +### What this program does This program is an implementation of an algorithm that calculates the date of the Sunday following the first full moon after the -spring equinoxe. (Also known as "Easter", defined this way by the +spring equinox. (Also known as "Easter", defined this way by the Nicaean Concilium in 325 Anno Domini.) The algorithm is attributed to the famous mathematician Carl Friedrich Gauss ["Meyers Handbuch ueber das Weltall", Meyer, 5th Edition, 1973, p149] and is suitable for anni domini within the Gregorian Calendar, that is, from 1582 AD to 2199 AD: +``` Let J be the year. If J is from 1582 to 1699, let M be 22, let N be 2 If J is from 1700 to 1799, let M be 23, let N be 3 @@ -51,29 +63,37 @@ Let c be the modulus of J divided by 7 Let d be the modulus of (19a + M) divided by 30 Let e be the modulus of (2b + 4c + 6d + N) divided by 7 +``` + The interesting Sunday is either: - March 22 + d + e or - April d + e - 9 (only one of them is a valid date) - +``` +March 22 + d + e or +April d + e - 9 (only one of them is a valid date) +``` + with the following exceptions: - April 26 must always be changed to April 19 - April 25 must be changed to April 18 if d is 28 and a greater than 10 +``` +April 26 must always be changed to April 19 +April 25 must be changed to April 18 if d is 28 and a greater than 10 +``` ### Example: - J = 1962, M = 24, N = 5 - a = J % 19 = 5 - b = J % 4 = 2 - c = J % 7 = 2 - d = 119 % 30 = 29 - e = 191 % 7 = 2 - -March 53 is invalid, so the result is April 22 1962 +``` +J = 1962, M = 24, N = 5 +a = J % 19 = 5 +b = J % 4 = 2 +c = J % 7 = 2 +d = 119 % 30 = 29 +e = 191 % 7 = 2 +``` -Why I think this is obfuscated ------------------------------- +March 53 is invalid, so the result is April 22 1962. + + +### Why I think this is obfuscated Apart from the calculation of the Easter date, the definition *and* calculation of which are obfuscations in their own right, @@ -101,22 +121,22 @@ Try to be as precise as can be and no one will comprehend what you mean. #### The formula: - comprehension = 1/(2**precision) +``` +comprehension = 1/(2**precision) +``` #### The interpretation: "Say nothing and everybody will understand." The `-I/usr/include` in the build file is needed by gcc on Solaris because -gcc's "fixed" header in gcc-lib/sparc-sun-solaris2.5/2.7.2/include/errno.h -is broken (sort of) because it has *two* identical extern -declarations of errno. This leads to an error due to the -redefinition of main. The `-I` option makes sure the working -/usr/include/errno.h is found first, which shouldn't harm on other -systems. +`gcc`'s "fixed" header in `gcc-lib/sparc-sun-solaris2.5/2.7.2/include/errno.h` +is broken (sort of) because it has *two* identical extern declarations of errno. +This leads to an error due to the redefinition of main. The `-I` option makes +sure the working /usr/include/errno.h is found first, which shouldn't cause any +problems on other systems. -Usage ------ +### Usage The program is run without arguments. It prints all dates in order. diff --git a/1996/schweikh2/README.md b/1996/schweikh2/README.md index 71f430b08..2aae527fa 100644 --- a/1996/schweikh2/README.md +++ b/1996/schweikh2/README.md @@ -1,20 +1,24 @@ # Best Algorithm - Jens Schweikhardt - DFN Network Operation Center - Schlartaeckerweg 3 (home address) - D-71384 Weinstadt - Germany +Jens Schweikhardt +DFN Network Operation Center +Schlartaeckerweg 3 (home address) +D-71384 Weinstadt +Germany + - http://www.uni-stuttgart.de/People/schweikhardt/home.html ## To build: - make all +```sh +make all +``` ## To run: - ./schweikh2 +```sh +./schweikh2 +``` The program accepts up to 4 parameters: @@ -29,11 +33,25 @@ The program accepts up to 4 parameters: ## Try: - ./schweikh2 15 1 0 0/0 +```sh +./schweikh2 15 1 0 0/0 +``` What happens if you pass only three parameters like the below? - ./schweikh2 15 1 0 +```sh +./schweikh2 15 1 0 +``` + +The author also suggests: + +```sh +while :; do grep -v '#' schweikh2.c; done + +``` + +(and we do too) which works with `sh`, `bash`, `ksh` and `zsh` as well. + ## Judges' remarks: @@ -41,7 +59,9 @@ What happens if you pass only three parameters like the below? The original program, with only slight obfuscations, may be found in `hunni.c`. The perl script, obfuscates it appropriately: - perl ./hunni.pl < hunni.c +```sh +perl ./hunni.pl < hunni.c +``` This entry was another crowd pleaser at the IOCCC BOF. @@ -79,34 +99,33 @@ modem noise. Lint the source. It's clean. How obfuscated... -What's the exit status? The program exits with J - 1 where J is the +What's the exit status? The program exits with `J - 1` where `J` is the return value from several non-void functions (needed to shut up -lint). The last assignment is J = printf ("%c", 10); so the exit -status is 0 unless the last printf failed, which is even a *useful* -status. A further obfuscation is the use of 10 instead of '\n'. -'\n' can not be constructed by token pasting, AFAIK. That's why `schweikh2` +lint). The last assignment is `J = printf ("%c", 10);` so the exit +status is 0 unless the last `printf` failed, which is even a *useful* +status. A further obfuscation is the use of `10` instead of `'\n'`. +`'\n'` can not be constructed by token pasting, AFAIK. That's why `schweikh2` is likely to produce occasional garbage on non-ASCII execution character set systems. -What this program does: ------------------------ +### What this program does -The program is an expression evaluator for a limited class of -expressions. Known operators are + - * /, operands are real numbers -(integers or fractions). The operands are restricted in that they must -differ by a constant value, for example 1 + 2 * 3 / 4 - 5. For any -combination of operators the expression is evaluated and compared to a -goal value. If they compare equal the expression is printed. If the goal -value is specified as 0/0 all expressions and results are printed. For -any fraction, the numerator and denominator are divided by their -greatest common divisor. +The program is an expression evaluator for a limited class of expressions. Known +operators are `+` `-` `*` `/`; operands are real numbers (integers or +fractions). The operands are restricted in that they must differ by a constant +value, for example `1 + 2 * 3 / 4 - 5`. For any combination of operators the +expression is evaluated and compared to a goal value. If they compare equal the +expression is printed. If the goal value is specified as `0/0` all expressions +and results are printed. For any fraction, the numerator and denominator are +divided by their greatest common divisor. The program accepts up to 4 parameters: - 1) The number of operators in the expression [default: 9] - 2) The value of the first operand [1] - 3) The (possibly negative) increment to the next operand [1] - 4) The goal value or 0/0 [42] + +1. The number of operators in the expression [default: 9] +2. The value of the first operand [1] +3. The (possibly negative) increment to the next operand [1] +4. The goal value or 0/0 [42] On ANSI/ISO C conformant systems (where long is at least 32 bits) overflow will occur in the default case (first operand 1, increment 1) @@ -116,28 +135,29 @@ systems the first parameter must not exceed 15. If long is at least 64 bits overflow will occur for more than 19 operators but you will probably wait quite some time for every of the -4^19 = 274,877,906,944 combinations to be evaluated... While I'm at it, -on a 50 MHz sparc, 4^11 expressions are evaluated in about 3 cpu -minutes (gcc -O3). +`4^19 = 274,877,906,944` combinations to be evaluated... While I'm at it, +on a 50 MHz SPARC, `4^11` expressions are evaluated in about 3 cpu +minutes (`gcc -O3`). -Sample arguments: ------------------ +### Sample arguments: - $ ./schweikh2 6 - $ ./schweikh2 7 0 - $ ./schweikh2 7 7 0 - $ ./schweikh2 8 9 -1 -67/21 - $ ./schweikh2 8 2 2/5 -98/25 - $ ./schweikh2 2 1/0 1 1/0 +```sh +$ ./schweikh2 6 +$ ./schweikh2 7 0 +$ ./schweikh2 7 7 0 +$ ./schweikh2 8 9 -1 -67/21 +$ ./schweikh2 8 2 2/5 -98/25 +$ ./schweikh2 2 1/0 1 1/0 +``` -Miscellaneous -------------- +### Miscellaneous The diamond pattern can be continued without a break. For a nice printout try this on your Bourne compatible shell: - - % while :; do grep -v '#' schweikh2.c; done +```sh +% while :; do grep -v '#' schweikh2.c; done +``` ## Copyright and CC BY-SA 4.0 License: diff --git a/1996/schweikh3/README.md b/1996/schweikh3/README.md index 5fe553148..18b4c8c2b 100644 --- a/1996/schweikh3/README.md +++ b/1996/schweikh3/README.md @@ -1,50 +1,56 @@ # Best Utility - Jens Schweikhardt - DFN Network Operation Center - Schlartaeckerweg 3 (home address) - D-71384 Weinstadt - Germany - - http://www.uni-stuttgart.de/People/schweikhardt/home.html +Jens Schweikhardt +DFN Network Operation Center +Schlartaeckerweg 3 (home address) +D-71384 Weinstadt +Germany + ## To build: - make all +```sh +make all +``` ## To run: -**WARNING**: Do not run this program without reading this text down to the end! +**WARNING: DO NOT RUN this program without reading this text down to the end!** It may render your system unusable for a limited amount of time or force you to reboot using the Big Red Button! This is **NOT** a joke. You have been warned. - ./schweikh3 - +```sh +./schweikh3 +``` ## Judges' remarks: The source fails to compile on compilers that recognize the inline -keyword by default. For gcc, you may need to use -ansi. +keyword by default. For gcc, you may need to use `-ansi`. -See the file, `schweikh3.info` for example output from various systems. +See the file [schweikh3.info](schweikh3.info) for example output from various +systems. But still it is a useful utility. To use try: - ./schweikh3 +```sh +./schweikh3 +``` and thanks for the virtual memories! :-) NOTE: On some systems such as SunOS, one may need to compile with: +```make ${CC} ${CFLAGS} \ -I. -D_POSIX_SOURCE '-Ddifftime(a,b)=(double)(b-a)' \ schweikh3.c -o schweikh3 +``` ## Author's remarks: -Why I think my entry is obfuscated ----------------------------------- +### Why I think my entry is obfuscated There are some layout obfuscations that hinder readability, like some (but not all) one character tokens in column 1. Includes, @@ -65,50 +71,53 @@ You have to select maximum ANSI C conformance of your compiler. The source fails to compile under a C++ compiler due to the `new' identifier which is a C++ reserved word: - $ g++ prog.c - prog.c:9: parse error before `new' - prog.c:16: parse error before `new' - prog.c:46: parse error before `void' - prog.c:65: parse error before `Lisp' - prog.c:68: parse error before `;' - [...] - prog.c:91: confused by earlier errors, bailing out +```sh +$ g++ schweikh3.c +schweikh3.c:9: parse error before `new' +schweikh3.c:16: parse error before `new' +schweikh3.c:46: parse error before `void' +schweikh3.c:65: parse error before `Lisp' +schweikh3.c:68: parse error before `;' +[...] +schweikh3.c:91: confused by earlier errors, bailing out +``` The source fails to compile on compilers that recognize the inline keyword by default, e.g. gcc: - $ gcc prog.c - prog.c:46: parse error before `void' - prog.c: In function `main': - prog.c:91: parse error before `inline' - prog.c: At top level: - prog.c:97: parse error before `void' +```sh +$ gcc schweikh3.c +schweikh3.c:46: parse error before `void' +schweikh3.c: In function `main': +schweikh3.c:91: parse error before `inline' +schweikh3.c: At top level: +schweikh3.c:97: parse error before `void' +``` The `-ansi` option to gcc fixes this. The source fails to compile on obsolete systems with obsolete -memory models due to the identifier `far' (to be honest: this is -untested :-). +memory models due to the identifier `far` (to be honest: this is +untested :-) ). Does your indent cope with backslash/newline pairs inbetween keywords like in "re\turn"? Solaris' indent inserts spaces and thereby renders the source uncompilable... The indented source will exhibit different semantics when indenting -changes the number of lines (due to using the __LINE__ macro in an +changes the number of lines (due to using the `__LINE__` macro in an expression). -And what about sizeof __TIME__? This one's for the philosophers -and physicists among us programmers. What is it? sizeof (char *)? -- no. -strlen ("hh:mm:ss")? -- no. It's the same as sizeof __DATE__ - -sizeof "no" :-) +And what about sizeof `__TIME__`? This one's for the philosophers +and physicists among us programmers. What is it? `sizeof (char *)`? -- no. +`strlen ("hh:mm:ss")`? -- no. It's the same as `sizeof __DATE__ - +sizeof "no"` :-) The program is POSIX conformant and lints without warning under Solaris' Sunpro lint. Allocated memory is correctly freed on all possible execution paths. -What this program does: ----------------------- +### What this program does This program tests your operating system's allocation honesty. It forks a child that will allocate as much as possible with byte @@ -140,8 +149,7 @@ the behaviour changes when calloc is used instead of malloc. For FreeBSD, the last two lines are not messages stemming from my program but issued by the syslog daemon. -Implementation remarks ----------------------- +### Implementation remarks How can we distinguish the three different OS types from the table above? @@ -154,10 +162,10 @@ where POSIX enters the scene. Type 3), thrashing, was the hardest part. The first attempt was to measure the elapsed processor time it takes to write a single byte -(using clock()). If a certain threshold is reached I assume the +(using `clock()`). If a certain threshold is reached I assume the system is thrashing. When thrashing, however, the process does not consume processor time in a noticeable amount any longer and I lose. -So I switched to measuring wall clock time using time(). On the one +So I switched to measuring wall clock time using `time()`. On the one system that I observe thrashing (Linux) this works (although the value returned by time seems to 'hang' sometimes when the OS thrashes. Exceeding a threshold of 5 seconds may be detected only after half a diff --git a/1996/westley/README.md b/1996/westley/README.md index 7151738c3..e179b41cf 100644 --- a/1996/westley/README.md +++ b/1996/westley/README.md @@ -1,53 +1,57 @@ # Best One Liner - Brian Westley (Merlyn LeRoy on Usenet) - 1906 James Ave. - St. Paul, MN 55105 - USA - - http://www.westley.org +Brian Westley (Merlyn LeRoy on Usenet) +1906 James Ave. +St. Paul, MN 55105 +US + ## To build: - make all +```sh +make all +``` [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed a segfault in this entry as well as it displaying environmental variables. Although the -scripts showed correct output these also segfaulted but with the fix they no -longer do. Now if argc < 5 (argv[4] is referenced) it will not do anything and -it will not segfault either (this was caused by the body of the for() loop which -is now empty (it doesn't appear to be needed at all). Note that this does make -some of the author's explanations / portability notes no longer valid but we -have kept them there for the interested. Thank you Cody for your assistance! +scripts showed correct output, it somewhat lessened the usability because they +segfaulted and showed (an) environmental variable, interspersed with the output +of the program. With the fix they no longer have this problem. If `argc < 5` +(`argv[4]` is referenced) it will not do anything and it will not segfault +either - this was caused by the body of the for() loop which is now empty (it +doesn't appear to be needed at all at least modernly). Note that you should +check the [westley.alt.c](westley.alt.c) file when reading the author's +comments. To see how to use the original see below. Thank you Cody for your +assistance! ## To run: - sh ./clock1 +```sh +sh ./clock1 +``` ## Try: - sh ./clock2 - -Also try: - - - sh ./clock2 +```sh +sh ./clock2 +``` And for a good time, try: - - sh ./clock3 +```sh +sh ./clock3 +``` ### Alternate code: -An alternate version of this entry, `westley.alt.c`, is provided. -The original is in [westley.alt.c](westley.alt.c) does not contain -the above mentioned fixes. +An alternate version of this entry, [westley.alt.c](westley.alt.c), is provided. +This version is the original code and does not contain the above mentioned +fixes. To compile this alternate version: @@ -55,6 +59,15 @@ To compile this alternate version: make alt ``` +To use it with the scripts try: + +```sh +WESTLEY=./westley.alt ./clock1 +WESTLEY=./westley.alt ./clock2 +WESTLEY=./westley.alt ./clock3 +``` + + ## Judges' remarks: Time and time again, Brian Westley seems to come up with a winner! @@ -64,47 +77,47 @@ understand it. ## Author's remarks: -This 1-line program allows various analog ASCII clocks -to print out the time; the ASCII clock is built from -the command line arguments, so many different types of -clocks can be generated. Three different scripts are -supplied to print out a grandfather clock, a mantle -clock that runs backwards, and a linear-style clock. -(they are `clock1`, `clock2`, and `clock3`) +This 1-line program allows various analog ASCII clocks to print out the time; +the ASCII clock is built from the command line arguments, so many different +types of clocks can be generated. Three different scripts are supplied to print +out a grandfather clock, a mantle clock that runs backwards, and a linear-style +clock. (they are `clock1`, `clock2`, and `clock3`) The program makes the following (possibly non-portable) assumptions: -1. Command line strings can be written to +1. Command line strings can be written to. -2. `argv[0]` can be written to as if it were a `long *` +2. `argv[0]` can be written to as if it were a `long *`. 3. The first three elements of the struct * returned by localtime() are seconds, -minutes, hours, and all are ints +minutes, hours, and all are ints. 4. My sample scripts assume ASCII, though this is not inherent in the code, just -my sample scripts +my sample scripts. -These assumptions are pretty reasonable. 2) can be eliminated -by makes the code larger. +These assumptions are pretty reasonable. 2) can be eliminated but makes the code +larger. The code is simple; the arguments passed are: - prog minute_map hour_map hand_symbol clock_image +```sh +./westley minute_map hour_map hand_symbol clock_image +``` The program merely takes the minute (0-59) and the hour (0-23) values, looks up the offsets in `minute_map` and `hour_map` and writes the `hand_symbol` for each into the `clock_image` string. This string is then printed. -The for() loop starts by calling time() with argv[0], so +The for() loop starts by calling `time()` with `argv[0]`, so the time value (a long) is written into the program name. -The for() control value is argc, which starts at 5, but -the /=2 statement is executed before the test, so the for() -loop is executed twice, with h=2, then h=1 (for hour & minute). +The for() control value is `argc`, which starts at `5`, but +the `/=2` statement is executed before the test, so the for() +loop is executed twice, with `h=2`, then `h=1` (for hour & minute). The statement of the for() loop takes the hour or minute -field of the struct returned by localtime() by casting it -to an int* and dereferencing element [h]. It is slightly +field of the struct returned by `localtime()` by casting it +to an `int *` and dereferencing element `[h]`. It is slightly smaller to use the trick `h[(int*)localtime(*m)]` instead of `((int*)localtime(*m))[h]`. diff --git a/1996/westley/clock1 b/1996/westley/clock1 index c79d1fbb4..d05dd1611 100755 --- a/1996/westley/clock1 +++ b/1996/westley/clock1 @@ -1,5 +1,6 @@ #!/usr/bin/env sh -./westley \ +${WESTLEY:=./westley} +${WESTLEY} \ "%%%&&&'''666EEESSSaaannn{{{zzzyyyxxxwwwhhhYYYKKK===000###\$\$\$" \ "34CQ_lkj[M?234CQ_lkj[M?2" \ " .*" \ diff --git a/1996/westley/clock2 b/1996/westley/clock2 index b2d779f9e..dc4bf21a9 100755 --- a/1996/westley/clock2 +++ b/1996/westley/clock2 @@ -1,5 +1,6 @@ #!/usr/bin/env sh -./westley \ +${WESTLEY:=./westley} +${WESTLEY} \ "%%%\$\$\$###000===KKKYYYhhhwwwxxxyyyzzz{{{nnnaaaSSSEEE666'''&&&" \ "32?M[jkl_QC432?M[jkl_QC4" \ " xX" \ diff --git a/1996/westley/clock3 b/1996/westley/clock3 index 5c4119ebd..4c8e544dc 100755 --- a/1996/westley/clock3 +++ b/1996/westley/clock3 @@ -1,5 +1,6 @@ #!/usr/bin/env sh -./westley \ +${WESTLEY:=./westley} +${WESTLEY} \ "123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_\`abcdefghijkl" \ "/\$%&'()*+,-./\$%&'()*+,-." \ " ||" \ diff --git a/1998/banks/README.md b/1998/banks/README.md index 232858e52..d891a9ebd 100644 --- a/1998/banks/README.md +++ b/1998/banks/README.md @@ -1,20 +1,23 @@ # Best of Show - Carl Banks - Penn State Department of Aerospace Engineering - 232 Hammond Building - University Park, PA 16802 - USA - - http://www.personal.psu.edu/users/c/w/cwb129/ +Carl Banks +Penn State Department of Aerospace Engineering +232 Hammond Building +University Park, PA 16802 +US + ## To build: - make all +```sh +make all +``` -## To run +## To run: - cat horizon.sc pittsburgh.sc | ./banks +```sh +cat horizon.sc pittsburgh.sc | ./banks +``` ## Judges' remarks: @@ -24,7 +27,11 @@ tight, well, we can just point them at this one. This program really pushes the envelope! The provided Makefile should work; you will need an X-ish system, and -a select() system call. More on building in the author remarks. +a `select()` system call. More on building in the author remarks. + +Carl Banks linked to (on his old website) an interesting article about this +entry, a flight simulator in just 1536 bytes, which can be found at +. ## Author's remarks: @@ -47,12 +54,11 @@ indicator, or compass. 0 is north, 90 is east, 180 is south, 270 is west. The third instrument is the altimeter, which measures your height above ground level in feet. --------- -Features --------- +### Features -* Simulator models a Piper Cherokee, which is a light, single-engine propeller -driven airplane. +* Simulator models a [Piper +Cherokee](https://en.wikipedia.org/wiki/Piper_PA-28_Cherokee), which is a light, +single-engine propeller driven airplane. * The airplane is modeled as a six degree-of-freedom rigid body, accurately reflecting its dynamics (for normal flight conditions, at least). @@ -65,7 +71,7 @@ reflecting its dynamics (for normal flight conditions, at least). heading indicator (compass), and an altimeter. * Flight controls may be mapped to any keys at compile time by redefining the -macros in the build file. Nice if your keyboard doesn't have arrow keys. (Or +macros in the Makefile. Nice if your keyboard doesn't have arrow keys. (Or if you still use vi. :-) * Time step size can be set at compile time. This is useful to reduce flicker @@ -81,9 +87,7 @@ seconds tend to have numerical stability problems.) * Fly through buildings! -------- -Scenery -------- +### Scenery Each of the `*.sc` files is a scenery file. The simulator program reads in the scenery from standard input on startup. @@ -92,55 +96,67 @@ less than 1000 total lines of input. Here is a brief description of the scenery files: - horizon.sc -- A horizon, nothing more. You will probably - always want to input this piece of scenery. +- [horizon.sc](horizon.sc) - mountains.sc -- An alternate horizon; a little more - mountainous. + A horizon, nothing more. You will probably always want to input this piece + of scenery. - pittsburgh.sc -- Scenery of downtown Pittsburgh. The downtown - area is initially located to your right. +- [mountains.sc](mountains.sc) - bb.sc -- Simple obstacle course. Try to fly over the - buildings and under the bridges. + An alternate horizon; a little more mountainous. - pyramids.sc -- Fly over the tombs of the ancient Pharaohs, - in this (fictitious) Egyptian landscape. +- [pittsburgh.sc]([pittsburgh.sc]) - river.sc -- Follow a flowing river from the sky. + Scenery of downtown Pittsburgh. The downtown area is initially located + to your right. + +- [bb.sc](bb.sc) + + Simple obstacle course. Try to fly over the buildings and under the + bridges. + +- [pyramids.sc](pyramids.sc) + + Fly over the tombs of the ancient Pharaohs, in this (fictitious) Egyptian + landscape. + +- [river.sc](river.sc) + + Follow a flowing river from the sky. A few examples of how to input scenery: - - cat horizon.sc pittsburgh.sc | ./banks - cat mountains.sc bb.sc | ./banks - cat mountains.sc river.sc pyramids.sc | ./banks +```sh +cat horizon.sc pittsburgh.sc | ./banks +cat mountains.sc bb.sc | ./banks +cat mountains.sc river.sc pyramids.sc | ./banks +``` You can simulate flying through a cloud bank as well: - ./banks < /dev/null +```sh +./banks < /dev/null +``` You will usually want at least a horizon, though. The format of scenery files is simple, by the way. They're just a list of 3-D coordinates, and the simulator simply draws line -segments from point to point as listed in the scenery file. 0 0 -0 is used to end a series of consecutive line segments. Note -that in the coordinate system used, the third coordinate -represents altitude in a negative sense: negative numbers are -positive altitudes. +segments from point to point as listed in the scenery file. `0 0 +0` is used to end a series of consecutive line segments. Note +that in the coordinate system used, _the third coordinate +represents **altitude** in a negative sense: negative numbers are +positive altitudes_. I'm sure you'll be making your own scenery files very soon!!! ----------------------------- -Alternate Build Instructions ----------------------------- +### Alternate Build Instructions Several options must be passed to the compiler to make the build -work. The provided build file has the appropriate options set +work. The provided [Makefile](Makefile) has the appropriate options set to default values. Use this section if you want to compile with different options. @@ -148,17 +164,17 @@ To map a key to a control, you must pass an option to the compiler in the format `-Dcontrol=key`. The possible controls you can map are described in the table below: - - Control Description Default Key - ------- ------------------------- ----------- - IT Increase throttle XK_Page_Up - DT Decrease throttle XK_Page_Down - FD Move stick forward XK_Up - BK Move stick back XK_Down - LT Move stick left XK_Left - RT Move stick right XK_Right - CS Center stick XK_Enter - +``` +Control Description Default Key +------- ------------------------- ----------- + IT Increase throttle XK_Page_Up + DT Decrease throttle XK_Page_Down + FD Move stick forward XK_Up + BK Move stick back XK_Down + LT Move stick left XK_Left + RT Move stick right XK_Right + CS Center stick XK_Enter +``` Values for the possible keys can be found in the X Windows header file ``. This file is most likely a @@ -173,10 +189,10 @@ option would be `-DCS=XK_space`. To set the time step size, you must pass the following option to the compiler: `-Ddt=duration`, where `dt` is literal, and where -duration is the time in seconds you want the time step to be. +`duration` is the time in seconds you want the time step to be. Two things to keep in mind when selecting a time step. Time -steps that are too large (more than about 0.03) will cause +steps that are too large (more than about `0.03`) will cause numerical stability problems and should be avoided. Setting the time step to be smaller than your clock resolution will slow down the simulator, because the system pauses for more time than diff --git a/1998/bas1/README.md b/1998/bas1/README.md index 553aef850..f1fce1f1c 100644 --- a/1998/bas1/README.md +++ b/1998/bas1/README.md @@ -1,63 +1,71 @@ # Best Encapsulation - Bas de Bakker - Pica, Centre for Library Automation - Statenweg 154 B (home address) - 3039 JN Rotterdam - The Netherlands +Bas de Bakker +Pica, Centre for Library Automation +Statenweg 154 B (home address) +3039 JN Rotterdam +The Netherlands ## To build: - make all +```sh +make all +``` -## To run +## To run: -If lpr on your system can print PostScript: +If `lpr` on your system can print PostScript: - ./bas1 | gunzip | lpr +```sh +./bas1 | gunzip | lpr +``` else, while in X Window System, - ./bas1 | gunzip | gv - +```sh +./bas1 | gunzip | gv - +``` + or: - ./bas1 | gunzip | gs -sDEVICE=pgmraw -sOutputFile='|xv -' - +```sh +./bas1 | gunzip | gs -sDEVICE=pgmraw -sOutputFile='|xv -' - +``` -## Judges' remarks +## Judges' remarks: The output is supposed to be a 3D maze, but it is somewhat more -than that. If you've seen any of the Maurits Escher's works, -you'll know what we're talking about. +than that. If you've seen any of the [Maurits +Escher's](https://en.wikipedia.org/wiki/M._C._Escher) +[works](https://mcescher.com/gallery/), you'll know what we're talking about. When trying to run the program with command line arguments, be generous. ## Author's remarks -BEMAZING -======== +### BEMAZING "You're in a twisty little maze of beams, all different." -Bemazing is "amazing" taken one step (letter) further. Bemazing +`Bemazing` is "amazing" taken one step (letter) further. `Bemazing` creates a 3D maze of beams. Try to go from the entrance (the unfinished beam in one corner) to the exit (the unfinished beam in the opposite corner) or vice versa. -For maximum portability, Bemazing is not tied to any window system, +For maximum portability, `Bemazing` is not tied to any window system, but creates postscript. The picture it makes will fit on either A4 or letter size paper. -In addition, because postscript is rather verbose, Bemazing creates +In addition, because postscript is rather verbose, `Bemazing` creates the postscript in gzip format, in order to save precious bits on your hard disk for the latest version of GNU Emacs (after all, you wouldn't want to use an editor without a psychoanalyze-pinhead function, now -would you). Again for maximum portability, Bemazing will take special +would you). Again for maximum portability, `Bemazing` will take special care that the binary output will not contain any newline or return characters that may get weird treatment on systems that do not use the One True Line Separator. -NOTES -===== +### NOTES Be sure to view the source with something that can display characters `\240-\377`. Use `LESSCHARSET=latin1`, `M-x` `standard-display-european` in @@ -66,8 +74,8 @@ GNU Emacs etc. The source does not use characters in the range HTML containing these control characters). Because this is not the obfuscated postscript contest, the postscript -does not contain any "for", "if" or other control structures. All the -logic is in the C code. There are only a few straightforward "def"s, +does not contain any `for`, `if` or other control structures. All the +logic is in the C code. There are only a few straightforward `def`s, because otherwise the output would become much larger. Try running `Bemazing` with command line arguments and see what diff --git a/1998/bas2/README.md b/1998/bas2/README.md index 1de51dd4f..66cc28621 100644 --- a/1998/bas2/README.md +++ b/1998/bas2/README.md @@ -1,32 +1,36 @@ # Best Small Program - Bas de Bakker - Pica, Centre for Library Automation - Statenweg 154 B (home address) - 3039 JN Rotterdam - The Netherlands +Bas de Bakker +Pica, Centre for Library Automation +Statenweg 154 B (home address) +3039 JN Rotterdam +The Netherlands ## To build: - make all +```sh +make all +``` ## To run: - ./bas2 < bas2.c +```sh +./bas2 < bas2.c +``` ## Judges' remarks: ### Questions to ponder: -Can you determine the relationship between the input and the -resulting numeric output? +Can you determine the relationship between the input and the resulting numeric +output? -The program was not designed to process files with a certain -octet value, what value is that? +The program was not designed to process files with a certain octet value, what +value is that? ### Hint and Extra Credit: -This entry points our a minor flaw in the IOCCC rules that has +This entry points out a minor flaw in the IOCCC rules that has been around since 1992. It processes a certain octet value in a way that differs from a strict reading of one of the official IOCCC rules. What is the rule and what is the octet @@ -44,7 +48,7 @@ done by matching the bit patterns. Minor obfuscations are: - Recursive main() instead of 2 loops (over input characters and over bits in the character). -- ? and || instead of if statements. +- `?` and `||` instead of if statements. ## Copyright and CC BY-SA 4.0 License: diff --git a/1998/chaos/README.md b/1998/chaos/README.md index c6c89cfba..895b27456 100644 --- a/1998/chaos/README.md +++ b/1998/chaos/README.md @@ -1,21 +1,26 @@ # Best Object Orientation -Alan De Smet -8531 Greenway Blvd. #206 -Middleton, WI 53562 -USA - +Alan De Smet +8531 Greenway Blvd. #206 +Middleton, WI 53562 +US + ## To build: - make chaos +```sh +make chaos + +``` NOTE: Some systems do not implement `halfdelay()` in their `libcurses`. You might try compiling with -lncurses if you have that library. Or you can build this entry without the `halfdelay()` call by: - make chaos_nohalf +```sh +make chaos_nohalf +``` [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) added a call to `endwin()` to restore terminal sanity (echo etc.) when exiting the program. @@ -24,19 +29,20 @@ Thank you Cody for your assistance! ## To run: - ./chaos +```sh +./chaos +``` ## Judge's Comments: This is the author's first IOCCC entry. We thought the entry was a nice example of a compact collection of obfuscations. -Can you figure our why, in some cases, it wants to read itself? +Can you figure out why, in some cases, it wants to read itself? ## Selected Author's Comments: - ### Usage The executable takes a single argument for the data file to use. @@ -46,8 +52,8 @@ worry about it... ### Summary -This is a simple ncurses 3D object viewer. The keys 'y', 'u', 'i', -'h', 'j', and 'k' rotate. 'a' and 'z' zoom in and out. 'q' quits. +This is a simple ncurses 3D object viewer. The keys `y`, `u`, `i`, +`h`, `j`, and `k` rotate. `a` and `z` zoom in and out. `q` quits. Given about 3 seconds of no input, it will start rotating until interrupted by user input. @@ -58,7 +64,7 @@ Memory malloced is never freed. This shouldn't be a big deal, since only one block is ever allocated, and the OS should recover it. My local flavor of lint doesn't seem to like the fact that I never -"return" from main. Feh, what does it know? Otherwise, ignoring +`return` from main. Feh, what does it know? Otherwise, ignoring lint's over protectiveness ("Of course I'm not using all of the functions defined in curses.h!"), it's lint clean. diff --git a/1998/df/README.md b/1998/df/README.md index 0d20083bf..d86ead80d 100644 --- a/1998/df/README.md +++ b/1998/df/README.md @@ -1,18 +1,22 @@ # Best Data Hiding - Daniel Fischer - VNetx.com GbR - Salenbergstrasse 11 (home address) - D 72250 Freudenstadt - German Federal Republic +Daniel Fischer +VNetx.com GbR +Salenbergstrasse 11 (home address) +D 72250 Freudenstadt +German Federal Republic ## To build: - make all +```sh +make all +``` ## To run: - ./df +```sh +./df +``` ## Judges' remarks; @@ -25,7 +29,7 @@ the program are used. Curiously, the program only works if its source is in the directory it's run in. More curiously, the program would fail if the program's -name's second letter wasn't "r" (the source has been changed for your +name's second letter wasn't `r` (the source has been changed for your convenience and this restriction does no longer exist). Modern design has come a long way since the unreadable, tightly-coupled @@ -37,7 +41,7 @@ Extra credit questions: - How many words does this entry use? - Can you add more words to the program and still make it work? -## Author's remarks +## Author's remarks: This program lets you guess English words. It displays an underscore for each letter in the word; guessing a letter that actually is in @@ -49,29 +53,28 @@ on the same line (completely solve it by entering "abcdefghijklmnopqrstuvwxyz"). Execution stops when all underscores have been replaced. -The program offers a number of different words to guess, time() is +The program offers a number of different words to guess, `time()` is used to pick one at random. All words are eight characters long. The source should compile with any ANSI C compiler (I used CodeWarrior w/ ANSI strict). Using non-ANSI compilers that implement the ANSI features it uses will not work (unless they defined `__STDC__ 1` which they shouldn't). Due to space restrictions, I did not use -any trigraph sequences. It does not require any special -D defines. +any trigraph sequences. It does not require any special `-D` defines. The source passes lint without any complaint (if invoked with `>/dev/null`). (My lclint is unable to recover from some parts of it.) -Actually, the code not only is compliant with the ANSI specifications, -but uses a near minimum subset of them. C keywords that were not -used have been re(de)fined to avoid unnecessary introduction of -new, unknown character patterns. The source also includes all ANSI -headers it needs (after most of the functions have been used), and -the declaration of main() follows the guidelines (but the return -type has a different meaning and the arguments are either mis- or -unused). There also may be some compiler warnings. These are not -bugs, but features. The more warnings, the better the compiler. -There wouldn't be any if I had been allowed to use some extra space -for prototypes etc. +Actually, the code not only is compliant with the ANSI specifications, but uses +a near minimum subset of them. C keywords that were not used have been +re(de)fined to avoid unnecessary introduction of new, unknown character +patterns. The source also includes all ANSI headers it needs (after most of the +functions have been used), and the declaration of `main()` follows the +guidelines (but the return type has a different meaning and the arguments are +either misused or unused). There also may be some compiler warnings. These are +not bugs, but features. The more warnings, the better the compiler. There +wouldn't be any if I had been allowed to use some extra space for prototypes +etc. Multiple defines are used (but not all of them define), and `#define y define` is used with `#y` but the code doesn't assume `#y` to expand @@ -91,10 +94,10 @@ file is not hard-coded, `__FILE__` is used instead. In the original version which was sent in to the contest, there were some restrictions on the file name: -- The second letter had to be a lowercase 'r'. -- The third letter could never be a '+' or a 'b'. +- The second letter had to be a lowercase `r`. +- The third letter could never be a `+` or a `b`. -Valid names would have been "pr4.c", "pr.c", "prog.c", "brownie.c" etc. +Valid names would have been `pr4.c`, `pr.c`, `prog.c`, `brownie.c` etc. My first private version would only run when compiled on a Friday. I decided it would be better this way... These restrictions have been removed for your convenience. @@ -104,15 +107,19 @@ want to know it at this time, please skip them. If this entry would by some mistake win the contest, please do not rot13 this - I hate rot13'd spoilers since it is somewhat complicated on a Mac to reverse them. Anyone out there should have enough discipline and -rot13 shouldn't be required, really. After all, we are no children +rot13 shouldn't be required, really. After all, we are not children anymore :-) +--- + This paragraph is not part of the author's remarks, but is a helpful gift from the judges; if you read too fast to stop yourself, this should give you enough time to stop, which you really need to do RIGHT NOW if you don't want to read the spoilers, which really do spoil everything, we mean it. +--- + The source file needs to be present because the words are read from it. The wordlist is encoded within the source using a 24 entry sliding dictionary where lowercase letters are offsets into the @@ -121,14 +128,14 @@ dictionary, and all other characters are ignored. The words are spread over six lines in the source; decoding starts on a line after a tab and a whitespace have been found, and stops on a newline. The grin after the "Demonic Smiley" actually is one encoded letter -while the string is completely ignored; and the "cut" in "cut here" +while the string is completely ignored; and the `cut` in "cut here" is required while "here" is not. "For extra credit", explain why the words are sorted alphabetically -(because I extracted them from a dictionary :-) +(because I extracted them from a dictionary :-) ) The file name had to fulfill the restrictions mentioned above -because `__FILE__+1` was used as a second parameter to fopen(). (It +because `__FILE__+1` was used as a second parameter to `fopen()`. (It essentially was `fopen(__FILE__,__FILE__+1)` ). This was an extra joke that does no longer exist in the released version. @@ -137,9 +144,9 @@ but the statement that opens the file and initializes the dictionary. Similarly, int and signed have been redefined (to save space, of course). -The main function (the guessing part) is between the last #else..#endif, -but still is declared before main(). The `5[O]()` in main() calls -this function. Similarly, Most indexing operations have been +The main function (the guessing part) is between the last `#else..#endif`, +but still is declared before `main()`. The `5[O]()` in `main()` calls +this function. Similarly, most indexing operations have been changed to this form; and I tried to write each such operation different. diff --git a/1998/dlowe/.gitignore b/1998/dlowe/.gitignore index ccc73cad8..b24712c80 100644 --- a/1998/dlowe/.gitignore +++ b/1998/dlowe/.gitignore @@ -1,2 +1,3 @@ dlowe dlowe.alt +README.poot.md diff --git a/1998/dlowe/README.md b/1998/dlowe/README.md index beb8ccaed..a5c795543 100644 --- a/1998/dlowe/README.md +++ b/1998/dlowe/README.md @@ -1,30 +1,52 @@ # Best Utility - David Lowe - Pootpoot - 67-D Manchester Street - San Francisco, CA 94110 - USA - - http://pootpoot.com/ +David Lowe +Pootpoot +67-D Manchester Street +San Francisco, CA 94110 +US ## To build: - make all +```sh +make all +``` -## To run +## To run: - ./dlowe < anyfile > pootfile +```sh +./dlowe < anyfile > pootfile +``` -## Judges' remarks +## Try: -Why is this entry would be considered a utility? Well because it +```sh +./dlowe < README.md +./dlowe < README.md > README.poot.md + +``` + +Why is there different output? + +### Alternate code: + +NOTE: The original entry was just a text based pootifier. To build +that version try: + +```sh +make dlowe.alt +./dlowe.alt < anyfile > pootfile +``` + +What's the difference between this and `dlowe`? + +## Judges' remarks: + +Why could this this entry be considered a utility? Well because it is able to convert content-free web pages into useful web pages. To see why, try using an online version, modified for use as -a CGI program: - - https://web.archive.org/web/20001025182142/http://pootpoot.com/poot/pootify?URL=http://www.microsoft.com +a CGI program: We are sure that you will find that new web page to make a much more consistent level of quality. :-) @@ -32,41 +54,39 @@ more consistent level of quality. :-) A CGI script such as: - #!/bin/sh - # pootify - a sample CGI pootifier - # - POOT="/usr/local/bin/dlowe" - LYNX="/usr/local/bin/lynx" - ECHO="/usr/bin/echo" - EXPR="/usr/bin/expr" - ${ECHO} "Content-type: text/html" - ${ECHO} - if [ -z "${QUERY_STRING}" ]; then - ${ECHO} "QUERY_STRING not found" - else - URL=`${EXPR} "$QUERY_STRING" : '[Uu][Rr][Ll]=\(.*\)'` - if [ -z "${URL}" ]; then - ${ECHO} "No URL given in QUERY_STRING" - elif [ X`${EXPR} "${URL}" : '[Ff][Ii][Ll][Ee]:'` != X0 ]; then - ${ECHO} "file: based URLs are not allowed" - else - ${LYNX} -restrictions=all -source "${URL}" | ${POOT} - fi - fi +```sh +#!/bin/sh +# pootify - a sample CGI pootifier +# +POOT="/usr/local/bin/dlowe" +LYNX="/usr/local/bin/lynx" +ECHO="/usr/bin/echo" +EXPR="/usr/bin/expr" +${ECHO} "Content-type: text/html" +${ECHO} +if [ -z "${QUERY_STRING}" ]; then + ${ECHO} "QUERY_STRING not found" +else + URL=`${EXPR} "$QUERY_STRING" : '[Uu][Rr][Ll]=\(.*\)'` + if [ -z "${URL}" ]; then + ${ECHO} "No URL given in QUERY_STRING" + elif [ X`${EXPR} "${URL}" : '[Ff][Ii][Ll][Ee]:'` != X0 ]; then + ${ECHO} "file: based URLs are not allowed" + else + ${LYNX} -restrictions=all -source "${URL}" | ${POOT} + fi +fi +``` can be used to pootify web pages. For further information see: - https://web.archive.org/web/20040326083431/http://www.pootpoot.com/poot/pootify/?URL=http%3A%2F%2Fwww.ioccc.org +```sh +https://web.archive.org/web/20040326083431/http://www.pootpoot.com/poot/pootify/?URL=http%3A%2F%2Fwww.ioccc.org +``` -NOTE: The original entry was just a text based pootifier. To build -that version try: - - make dlowe.alt - ./dlowe.alt < anyfile > pootfile - -## Author's remarks +## Author's remarks: This program is a text filter, it reads stdin and outputs the "corrected" text to stdout. @@ -76,9 +96,9 @@ its purpose and mode of operation are not terribly obvious. More importantly, it is a tool for further obfuscation, in that it can take any text and render it unintelligible. -Suggested uses: add to your MANROFFSEQ environment variable for man page -enjoyment; use it to turn the GPL into the PPL; see what happens when you -run perl4 programs after they've been run through it; "encrypt" sensitive +Suggested uses: add to your `MANROFFSEQ` environment variable for man page +enjoyment; use it to turn the GPL into the `PPL`; see what happens when you +run `perl4` programs after they've been run through it; "encrypt" sensitive (but unnecessary) documents... ## Copyright and CC BY-SA 4.0 License: diff --git a/1998/dloweneil/README.md b/1998/dloweneil/README.md index 83a675b82..f7858b2bc 100644 --- a/1998/dloweneil/README.md +++ b/1998/dloweneil/README.md @@ -1,37 +1,56 @@ # Most Fun - David Lowe Neil Mix - Pootpoot Pootpoot - 67-D Manchester Street 1490 Sacramento Street #4G - San Francisco, CA 94110 San Francisco, CA 94110 - USA USA +David Lowe +Pootpoot +67-D Manchester Street +San Francisco, CA 94110 +US - http://pootpoot.com/ +Neil Mix +Pootpoot +1490 Sacramento Street #4G +San Francisco, CA 94110 +US ## To build: - make all +```sh +make all +``` -## To run +## To run: - ./pootris +```sh -## Judges' remarks +./pootris [X size of board] [Y size of board] +``` -Read the Author's remarks below. We believe that your experience may -mirror one of our experiences: +Pressing `a` moves the current letter position counterclockwise around the +border of the playing field. + +Pressing `s` moves the current letter one position clockwise around the border +of the playing field. + +Pressing `d` drops the current letter onto the board. + +## Judges' remarks: + +Read the authors' remarks below to find out how to play. We believe that your +experience may mirror one of our experiences: > Originally, I didn't appreciate the game. Then I actually read the > description of the controls. I started playing. I struggled. > I spelled my first "poot". I was hooked ... -## Author's remarks +## Author's remarks: -Usage: +### Usage - ./pootris [X size of board] [Y size of board] +```sh +./pootris [X size of board] [Y size of board] +``` -### Synopsis: +### Synopsis The object of this game is to spell "POOT" as much as possible. There is no time pressure. You're given one letter at a time (sort of randomly @@ -39,68 +58,71 @@ chosen from the set 'P', 'O', and 'T') and you get to move it freely around the border of the playing board, and decide when and where to drop it into the board. Sound easy? Of course, there's a catch... -### Controls: - +### Controls Only three controls: 'a' moves the current letter one position counterclockwise around the border of the playing field. + 's' moves the current letter one position clockwise around the border of the playing field. + 'd' drops the current letter onto the board. To quit, send a fatal signal to the process. -### Rules of motion: +### Rules of motion The different letters move in different directions once dropped onto the board: -'P' moves diagonally, at a 45 degree angle and in a clockwise direction around +`P` moves diagonally, at a 45 degree angle and in a clockwise direction around the board once dropped. -'O' moves in a straight line perpendicular to the border from which it is + +`O` moves in a straight line perpendicular to the border from which it is dropped. -'T' moves diagonally, at a 45 degree angle and in a counterclockwise direction + +`T` moves diagonally, at a 45 degree angle and in a counterclockwise direction around the board once dropped. The letters bounce off the top and sides of the board. They bounce in a -'natural' way, with the exception that 'O's will fall straight down if they hit +'natural' way, with the exception that `O`s will fall straight down if they hit a side wall. The letters stop when they hit another letter or the bottom of the board. -### Rules of spelling: +### Rules of spelling -- When you spell 'POOT' on the board, in any direction, the letters comprising +- When you spell `POOT` on the board, in any direction, the letters comprising the word will disappear, and any letters which may have accumulated above the disappeared letters will 'fall'. -- Letters can be used in multiple spellings of 'POOT'. +- Letters can be used in multiple spellings of `POOT`. - Chain reactions are possible. -### Rules of scoring: +### Rules of scoring - You get one (1) point for each letter you drop onto the board. -- You get a bunch of points for spelling 'POOT'. More if you spell it in more +- You get a bunch of points for spelling `POOT`. More if you spell it in more than one way simultaneously. -### Some of the obfuscations: +### Some of the obfuscations - Several different coordinate systems are used. There's the "real" X by Y system used for curses, the "inside the box" X by Y system used for moving -things around and finding instances of "POOT" inside the box, and the position -of the current letter, which is a single value from 0 to 2 * xsize + 2 * ysize - -1. +things around and finding instances of `POOT` inside the box, and the position +of the current letter, which is a single value from 0 to `2 * xsize + 2 * ysize +- 1`. -- The fact that x%3 is a perfect hash function for x values 'P', 'O' and 'T' is -used. +- The fact that `x%3` is a perfect hash function for `x` values `P`, `O` and `T` +is used. -- Of course, the code is as hideous as possible, and spells poot for fun (It's +- Of course, the code is as hideous as possible, and spells `poot` for fun (It's also exactly 3217 bytes in length, with exactly 1536 counted characters for -purposes of this contest.) +purposes of this contest.. - Love that modulus operator! Mmmm... @@ -109,7 +131,7 @@ served the dual purposes of compacting the code and making it trickier to understand. I'm thinking of the equations used to convert between coordinate systems when dropping pieces into the game board. -- Simple and silly ones: short, meaningless (and sometimes misleading (see 'x')) +- Simple and silly ones: short, meaningless (and sometimes misleading (see `x`)) variable names; hard-coded ASCII numeric values used for character constants; using goto for fun and profit; reusing and re-purposing variables in different places. @@ -118,7 +140,7 @@ places. ### Some things I wish I could have fit into this, but didn't have the space: -- Seeding the random number generator (doh!) +- Seeding the random number generator (doh!). - Something to detect when the game is over. diff --git a/1998/dorssel/Makefile b/1998/dorssel/Makefile index 8d941e59a..3bfaeef52 100644 --- a/1998/dorssel/Makefile +++ b/1998/dorssel/Makefile @@ -111,7 +111,7 @@ ENTRY= dorssel PROG= ${ENTRY} # OBJ= ${PROG}.o -DATA= dorssel.hint +DATA= dorssel.md TARGET= ${PROG} # ALT_OBJ= diff --git a/1998/dorssel/README.md b/1998/dorssel/README.md index df4113100..10180692d 100644 --- a/1998/dorssel/README.md +++ b/1998/dorssel/README.md @@ -1,29 +1,35 @@ # Obsolescent Feature - Frans van Dorsselaer - Bakker Industrial Automation - Kaiserstraat 35 - NL-2311 GP Leiden - The Netherlands +Frans van Dorsselaer +Bakker Industrial Automation +Kaiserstraat 35 +NL-2311 GP Leiden +The Netherlands ## To build: - make all +```sh +make all +``` ## To run: - ./dorssel - # input some text +```sh +./dorssel +# input some text - echo text | ./dorssel +echo text | ./dorssel +``` ## Try: - echo Simple as 123 | ./dorssel - echo 'Binary as simple as 1, 10 11.' | ./dorssel - echo '.... --- .-- -.. --- . ... .. - -.. --- - .... .- -' | ./dorssel - echo 'HOW DOES IT DO THAT' | ./dorssel - echo 'HOW DOES IT DO THAT' | ./dorssel | ./dorssel +```sh +echo Simple as 123 | ./dorssel +echo 'Binary as simple as 1, 10 11.' | ./dorssel +echo '.... --- .-- -.. --- . ... .. - -.. --- - .... .- -' | ./dorssel +echo 'HOW DOES IT DO THAT' | ./dorssel +echo 'HOW DOES IT DO THAT' | ./dorssel | ./dorssel +``` ## Judges' remarks: @@ -52,15 +58,14 @@ You might also want to read the [dorssel.hint](dorssel.hint) file. ## Author's remarks: -Usage -===== +### Usage This program converts ASCII to Morse code, and vice versa. The program reads in lines from standard input and writes its result to standard output. The direction of conversion is determined on a per line basis. Each line must consist of a maximum of 952 characters -followed by a new line character, they must not contain any NUL +followed by a new line character and they must not contain any NUL characters. Otherwise, some characters may be lost in the conversion. - Encoding to Morse code: The program knows the Morse codes for all Latin @@ -69,40 +74,46 @@ are replaced by an ASCII space ' '. Morse code per converted character is written as a sequence of '.' and '-' characters, each sequence followed by a space. -- Decoding from Morse code: Morse code should be typed as sequences of '.' and -'-' characters, separated by a space. Extra spaces will be echoed back (to -separate words). Unknown sequences will be converted to a '?' character. +- Decoding from Morse code: Morse code should be typed as sequences of `.` and +`-` characters, separated by a space. Extra spaces will be echoed back (to +separate words). Unknown sequences will be converted to a `?` character. -Notes -===== +### Notes The program assumes both source and execution character sets to be ASCII. As far as I can tell, the program is conforming and does not invoke undefined behavior. -Hints -===== +### Hints -Try +Try: - ./dorssel < dorssel.c | ./dorssel +```sh +./dorssel < dorssel.c | ./dorssel +``` to see what variables, numbers, and functions are used. (Does a better job than most C beautifiers). - Filter your text twice (as in the previous sample) to obtain a version of your -text that can be reversibly morsified, i.e. +text that can be reversibly Morsified, i.e. - ./dorssel | ./dorssel | ./dorssel | ./dorssel +```sh +./dorssel < dorssel.c | ./dorssel | ./dorssel | ./dorssel +``` is the same as - ./dorssel | ./dorssel +```sh +./dorssel < dorssel.c | ./dorssel +``` - The file "dorssel.hint" contains all the information needed to understand this program. For an obfuscated spoiler, try - ./dorssel < dorssel.hint +```sh +./dorssel < dorssel.hint +``` ## Copyright and CC BY-SA 4.0 License: diff --git a/1998/dorssel/dorssel.hint b/1998/dorssel/dorssel.md similarity index 70% rename from 1998/dorssel/dorssel.hint rename to 1998/dorssel/dorssel.md index 0a92fa954..957bc1cfc 100644 --- a/1998/dorssel/dorssel.hint +++ b/1998/dorssel/dorssel.md @@ -1,14 +1,18 @@ +# Information about this entry + Morse codes for letters and digits use sequences of 1 to 5 (inclusive) Morse symbols (denoted as '.' or '-'), e.g. +``` E . Z --.. 3 ...-- +``` -(BTW: digits always have 5 symbols, letters 1 to 4. I didn't use this fact) +(BTW: digits always have 5 symbols, letters 1 to 4. I didn't use this fact.) -Of course we can encode these symbols with bits in a byte. I chose '-' -to be a bit set to 0, '.' to be a bit set to 1. Characters in C are at +Of course we can encode these symbols with bits in a byte. I chose `-` +to be a bit set to 0, `.` to be a bit set to 1. Characters in C are at least 8 bits, but they are either signed or unsigned. To be portable, I've used only values from 0 to 127 (inclusive) (both in the encoding of Morse codes, as well as in subexpressions in the program). Hence we @@ -18,42 +22,52 @@ the source code excessively large ;-) The least significant bit contains the first symbol of a Morse code, so we have +``` E > 0......1 Z > 0...1100 3 > 0..00111 +``` The dots have still to be determined. But we also need to encode the length of the sequence. Since there are only 4 different kind of lengths, two bits would suffice, e.g. +``` E > 000....1 Z > 010.1100 3 > 01100111 +``` That means bits 6 and 5 set to 00 is length 1, set to 01 is length 2, etc. But this would mean that we would have to extract the length into a counter before shifting out each symbol, such as +```c length = (encoding & 96) >> 5; do { putchar(encoding & 1 ? '-' : '.'); encoding >>= 1; } while (length--); +``` We can also use the remaining bits to *include* the counter +``` length 1: 00000.1x E > 00000.11 length 2: 0000.1xx length 3: 000.1xxx length 4: 00.1xxxx Z > 00.11100 length 5: 0.1xxxxx 3 > 0.100111 +``` With 1 bit still to be chosen freely (let's assume it is 0). Now we can do +```c do { putchar(encoding & 1 ? '-' : '.'); encoding >>= 1; while (encoding > 1); +``` As you see, the encoded Morse sequence can be the counter itself. But this is not very pleasant, as some Morse sequences will end up having @@ -61,66 +75,75 @@ an ASCII value < 32, i.e. they will be control codes. This would make the initializing (encoding) string awkward. Hence I came up with the following +``` length 1: 0010010x E > 00100101 (= '%') length 2: 001010xx length 3: 00110xxx length 4: 0100xxxx Z > 01001100 (= 'L') length 5: 011xxxxx 3 > 01100111 (= 'g') +``` Notice these encodings in the initialization string. Only the coding for -'5' needs an escape (5 = ..... > 01111111 = '\177'). The way the length +`5` needs an escape (`5 = ..... > 01111111 = '\177'`). The way the length is encoded still allows the encoding to be its own counter: +```c do { putchar(encoding & 1 ? '-' : '.'); encoding = (encoding + 32) >> 1; } while (encoding > 35); +``` -The last shift will always result in 00100010, hence the test for >35. -Note that the calculation for the next value of `encoding' is done at int -precision, so that the actual value of the char remains <= 127. +The last shift will always result in `00100010`, hence the test for `>35`. +Note that the calculation for the next value of `encoding` is done at int +precision, so that the actual value of the char remains `<= 127`. -The character '-' (ASCII 45) and '.' (ASCII 46) are conveniently in +The character `'-'` (ASCII 45) and `'.'` (ASCII 46) are conveniently in sequence, so the putchar can simply be +```c putchar(45 + encoding % 2); +``` -I used the modulo operator this time, because '+' takes precedence over '&'. +I used the modulo operator this time, because `+` takes precedence over `&`. The assignment can be incorporated into the while control test, and a do-while loop with a body of a single expression statement can be written as a while loop with a comma operator in the test: +```c while(putchar(45 + encoding % 2), encoding = encoding + 32 >> 1); +``` Voila. -Now, the decoding of Morse codes is just the reverse. We shift in 0's -and 1's as we scan the line. But: we have to scan from back to front +Now, the decoding of Morse codes is just the reverse. We shift in `0`s +and `1`s as we scan the line. But: we have to scan from back to front (the left most Morse symbol is in the least significant bit, and thus has to shifted in last). The test for the scanning while loop must -stop when there are no more '.' or '-' on the left. Hence we need a +stop when there are no more `.` or `-` on the left. Hence we need a terminating character in front of the line. The input line is read one past the encoding string (into the same character array) the terminating -character for the reverse scan is therefore provided by the implicit '\0' +character for the reverse scan is therefore provided by the implicit `'\0'` of the array initializer ! The test also stops when at most 5 symbols have been shifted in. The encoded character is then looked up in the encoding string with -memchr (why memchr is explained later). Either a '?' (when there are +`memchr()` (why `memchr()` is explained later). Either a `?` (when there are more than 5 consecutive Morse symbols, or if the sequence is unknown) -or the decoded character is printed. Or a ' ' if there was an extra +or the decoded character is printed. Or a `' '` if there was an extra space in the source line. Note the use of "or" in these last sentences, as they explain the use of the conditional operator. -The strspn calls need either " .-" or ".-" as argument. Of course they +The `strspn` calls need either `" .-"` or `".-"` as argument. Of course they are overlapped. I put these strings between the encodings for digits -and letters. This is OK, since neither of these characters, or the '\0', -is a valid encoding ! We must, however, use memchr instead of strchr in -the decoding lookup because of this '\0'. Since it is far more obscure +and letters. This is OK, since neither of these characters, or the `'\0'`, +is a valid encoding ! We must, however, use `memchr()` instead of `strchr()` in +the decoding lookup because of this `'\0'`. Since it is far more obscure this way, I hope you'll forgive me. The outline of the program is roughly as follows +``` while (more lines) { if (line is in morse) { while (more characters) { @@ -137,23 +160,25 @@ while (more lines) { putchar(' '); } } +``` -Because of the *two* while(more characters) loops are the same, I've -exchanged the if(line is in morse) and the two while loops (so there -is *single* while loop). However, we must now store the if(line is in -morse) test for efficiency (it would be stupid to test the entire line -for every character). This is done in l[0] ! (the first encoding is -thus in l[1]). The memchr decoding lookup is not disturbed, because the -test is always 0 for Morse lines, and '\0' is not a possible encoding. -l[0] is also used as the temporary shift character while encoding a -line of text. This does not disturb the if (line is in morse) test, -as the temporary l[0] will remain != 0. +Because of the *two* `while(more characters)` loops are the same, I've +exchanged the `if(line is in morse)` and the two while loops (so there +is *single* while loop). However, we must now store the `if(line is in +morse)` test for efficiency (it would be stupid to test the entire line +for every character). This is done in `l[0]` ! (the first encoding is +thus in `l[1]`). The `memchr()` decoding lookup is not disturbed, because the +test is always `0` for Morse lines, and `'\0'` is not a possible encoding. +`l[0]` is also used as the temporary shift character while encoding a +line of text. This does not disturb the `if (line is in morse)` test, +as the temporary `l[0]` will remain `!= 0`. -I've put the if's in the above layout into a single switch. Hope you don't +I've put the `if`s in the above layout into a single switch. Hope you don't mind ;-) Summary of the use of l[999]: +``` l[0] result of "is this line in morse" test l[0] temporary shift during encoding l[0] - l[33] Morse codings (letters and digits, plus garbage) @@ -161,13 +186,14 @@ l[11] - l[14] strspn argument l[12] - l[14] strspn argument l[34] terminator for backward decoding l[35] - l[998] input line +``` -***** +--- Selected notes: -- We don't need to declare isalnum() (or include ctype.h) as its implicit +- We don't need to declare `isalnum()` (or include ctype.h) as its implicit declaration is correct (int argument, int result). This is not so for - strlen(), strspn(), and memchr() as they use size_t. + `strlen()`, `strspn()`, and `memchr()` as they use `size_t`. - During development, my gcc 2.7.2.3 had an internal compiler error (signal 6) on code that was correct ! - lclint 2.4b thinks that "the observer is modified" a couple of times, @@ -176,7 +202,7 @@ Selected notes: - lclint 2.4b is positive the second while loop is infinite, whereas it is not. -***** +--- .. - .... .. -. -.- - .... .. ... ... .--. --- .. .-.. . .-. .. ... -- --- .-. . --- -... ..-. ..- ... -.-. .- - . -.. - .... .- -. - .... . .--. .-. --- --. .-. .- -- diff --git a/1998/fanf/README.md b/1998/fanf/README.md index fe3ac9882..e45eb06b0 100644 --- a/1998/fanf/README.md +++ b/1998/fanf/README.md @@ -1,24 +1,27 @@ # Most Obfuscated Translator - Tony Finch - Demon Internet - 322 Regent's Park Road - Finchley - London N3 2QQ - United Kingdom - - http://www.inch.demon.co.uk/ +Tony Finch +Demon Internet +322 Regent's Park Road +Finchley +London N3 2QQ +United Kingdom + ## To build: - make all +```sh +make all +``` NOTE: This may take a while. Some systems may have problems building this entry because of the system resources it requires. -## To run +## To run: - ./fanf +```sh +./fanf +``` ### To use: @@ -26,25 +29,27 @@ this entry because of the system resources it requires. Enter an expression on standard input. Here are some sample expressions that you can use: - ((\a(\b(\c(d)))) e) +``` +((\a(\b(\c(d)))) e) - (\f\g\x - ( - (g x) (f x) - ) K K z - ) +(\f\g\x + ( + (g x) (f x) + ) K K z +) - (\f(\f\g\x( (f((\a(g(b))) e)) (g x) ) K K z)) +(\f(\f\g\x( (f((\a(g(b))) e)) (g x) ) K K z)) - (Y\f\n - ((= n 0) - 1 - (* n (f (- n 1))) - ) - ) +(Y\f\n + ((= n 0) + 1 + (* n (f (- n 1))) + ) +) +``` ## Judges' remarks: @@ -55,19 +60,21 @@ impressed by this program! See the file [fanf.lambda](fanf.lambda) for more examples of lambda calculus source. -Notice how large the code grows from the fanf.c into the final -fanftmp2.c C program. Take a look at that final C program again, +Notice how large the code grows from the [fanf.c](fanf.c) into the final +`fanftmp2.c` C program. Take a look at that final C program again, can you begin to understand what it is doing? Look at the first stage of the C pre-processing: - cc fanf.c -E > fanftmp1.c +```sh +cc fanf.c -E > fanftmp1.c +``` -Skip to the bottom of fanftmp1.c (after all of the #include header -stuff ... look for a line of the form: # 2 "fanf.c" near the bottom) +Skip to the bottom of `fanftmp1.c` (after all of the `#include` header +stuff ... look for a line of the form: `# 2 "fanf.c"` near the bottom) and look at the resulting code. This code, when C pre-processed -will expand into over 342 times the original code (ignoring #include -headers) to produce fanftmp2.c. That program in turn, when compiled +will expand into over 342 times the original code (ignoring `#include` +headers) to produce `fanftmp2.c`. That program in turn, when compiled translates a single lambda expression on standard input into combinator expressions on standard output. @@ -83,8 +90,7 @@ theoretical computer science. The application it implements is a program for translating lambda expressions into combinator expressions. -What the program does -===================== +### What the program does The syntax of lambda expressions recognised by the program is as follows: The basic atoms are variables which are single characters other @@ -102,10 +108,12 @@ simple expression is `(I a)` which is equivalent to `(\x(x) a)`, which has the value `a`. Another function called `K` is defined as `\x\y(x)` and it evaluates as follows: +``` K p q -> \x\y(x) p q -> \y(p) q -> p +``` Another function of interest is `S`, defined as `\f\g\x((f x) (g x))`. My program demonstrates the fact that any lambda expression can be @@ -114,6 +122,7 @@ only `S`, `K`, `I` (the combinators), and application, with no variables or lambda abstractions. In fact, even `I` is unnecessary, since it is equivalent to `S K K`: +``` I z -> \a(a) z -> z @@ -123,6 +132,7 @@ since it is equivalent to `S K K`: -> (K z) (K z) -> \x\y(x) z (K z) -> z +``` The algorithm for translating lambda expressions into combinator expressions works as follows. There are three forms of lambda expression @@ -143,6 +153,7 @@ abs a `a` -> `I` E.g. suppose we had combinator expressions for `+` and `3` and we wanted to see what the combinator expression for doubling 3 looked like: +``` trans `\x(+ x x) 3` -> (trans `\x(+ x x)`) (trans `3`) -> (abs x (trans `+ x x`)) `3` @@ -151,243 +162,267 @@ to see what the combinator expression for doubling 3 looked like: -> `S` (`S` (abs x `+`) (abs x `x`)) `I` `3` -> `S` (`S` (`K +`) `I`) `I` `3` -> `S (S (K +) I) I 3` +``` We can then check that this evaluates to the expected result: +``` S (S (K +) I) I 3 -> S (K +) I 3 (I 3) -> K + 3 (I 3) (I 3) -> + (I 3) (I 3) -> + 3 3 +``` - It is possible to perform a slightly more compact translation with a - couple of simple optimisations. For example, note that `K (a b)' is the - same as `S (K a) (K b)', because +It is possible to perform a slightly more compact translation with a +couple of simple optimisations. For example, note that `K (a b)` is the +same as `S (K a) (K b)`, because +``` K (a b) x -> a b +``` and +``` S (K a) (K b) x -> K a x (K b x) -> a b +``` - Also, `S (K a) I' is the same as just `a' because +Also, `S (K a) I` is the same as just `a` because +``` S (K a) I x -> K a x (I x) -> a x +``` - The program simply reads a lambda expression from the standard input, - translates it into a combinator expression using the transformation and - optimisations described above, and prints out the result. +The program simply reads a lambda expression from the standard input, +translates it into a combinator expression using the transformation and +optimisations described above, and prints out the result. - Why this is a practical application - =================================== +### Why this is a practical application - Combinator expressions are easier to evaluate than lambda expressions - because there are no problems with variables. For example, if I naively - evaluated the expression `\x\y(x y) y' I might get `\y(y y)' which is - not the same as the correct result because the first `y' in the body - should refer to a global `y' rather than the local one. David Turner was - the first person to realise that because of this fact, SK combinators - provide a simple way to implement non-strict functional programming - languages, either in software or directly in hardware. +Combinator expressions are easier to evaluate than lambda expressions +because there are no problems with variables. For example, if I naively +evaluated the expression `\x\y(x y) y` I might get `\y(y y)` which is +not the same as the correct result because the first `y` in the body +should refer to a global `y` rather than the local one. David Turner was +the first person to realise that because of this fact, SK combinators +provide a simple way to implement non-strict functional programming +languages, either in software or directly in hardware. - My program demonstrates this by being based on a combinator evaluation - engine which is used to implement a language called "OFL" (pronounced - like "offal" and short for "Obfuscated Functional Language"). I then - used OFL to implement all the high-level functionality described above. - This contributes a lot to the obfuscation because even small amounts of - OFL are quite unpalatable, and large expressions are completely - incomprehensible. +My program demonstrates this by being based on a combinator evaluation +engine which is used to implement a language called `OFL` (pronounced +like "offal" and short for "Obfuscated Functional Language"). I then +used `OFL` to implement all the high-level functionality described above. +This contributes a lot to the obfuscation because even small amounts of +`OFL` are quite unpalatable, and large expressions are completely +incomprehensible. - It is fairly well known that the lambda calculus (and hence SK - combinators) can compute anything, but mere computation is no use if you - cannot communicate with the world. This is why OFL includes a few - concessions to reality: a combinator `E' for representing characters and - testing them for equality, two IO combinators, `G' and `P', for reading - and writing characters respectively, and a combinator `J' for - representing "false". I also implemented the `Y' combinator directly - rather than in terms of the primitive combinators, since it only - required five characters to do so (viz. `Y W q Q g'). However this code - is not enabled because the definition of Y in terms of other combinators - is more cute. +It is fairly well known that the lambda calculus (and hence SK +combinators) can compute anything, but mere computation is no use if you +cannot communicate with the world. This is why `OFL` includes a few +concessions to reality: a combinator `E` for representing characters and +testing them for equality, two IO combinators, `G` and `P`, for reading +and writing characters respectively, and a combinator `J` for +representing `false`. I also implemented the `Y` combinator directly +rather than in terms of the primitive combinators, since it only +required five characters to do so (viz. `Y W q Q g`). However this code +is not enabled because the definition of `Y` in terms of other combinators +is more cute. - The `E' combinator comes in a large number of forms, one for each - character and one for end of file. It is written `E(c)' for the variant - of `E' corresponding to the character `c'. An expression of the form - `E(c) x' is evaluated by first evaluating `x'. If `x' doesn't evaluate - to some form of `E', then evaluation of the expression terminates. If - `x' evaluates to `E(c)', then the expression evaluates to `K'. If `x' - evaluates to `E(d)' (where `d' is a different character to `c'), then - the expression evaluates to `J'. +The `E` combinator comes in a large number of forms, one for each +character and one for end of file. It is written `E(c)` for the variant +of `E` corresponding to the character `c`. An expression of the form +`E(c) x` is evaluated by first evaluating `x`. If `x` doesn't evaluate +to some form of `E`, then evaluation of the expression terminates. If +`x` evaluates to `E(c)`, then the expression evaluates to `K`. If `x` +evaluates to `E(d)` (where `d` is a different character to `c`), then +the expression evaluates to `J`. - `K' and `J' are used to represent "true" and "false" respectively; they - correspond exactly to the standard lambda calculus representations of - true and false, viz. `\t\f(t)' and `\t\f(f)' respectively. In this way a - conditional expression can just be written `cond then else', which is - even more terse than C's `cond ? then : else'. An expression that - compares a character with `a', say, can be written in the rather - obfuscated form `E('a') char then else'. +`K` and `J` are used to represent `true` and `false` respectively; they +correspond exactly to the standard lambda calculus representations of +true and false, viz. `\t\f(t)` and `\t\f(f)` respectively. In this way a +conditional expression can just be written `cond then else`, which is +even more terse than C `cond ? then : else`. An expression that +compares a character with `a`, say, can be written in the rather +obfuscated form `E('a') char then else`. - The `P' combinator, like the `E' combinator, starts off by evaluating - its first argument and checking that it is some form of `E'. It then - writes that character on stdout, and finally it calls its second - argument as a function with the argument `I', i.e. - P x f -> f I - with a side-effect. +The `P` combinator, like the `E` combinator, starts off by evaluating +its first argument and checking that it is some form of `E`. It then +writes that character on stdout, and finally it calls its second +argument as a function with the argument `I`, i.e. - The `G' combinator just reads a character from stdin then calls its - argument as a function with the appropriate `E' combinator as an - argument, i.e. - G f -> f E(c) - with a side-effect. +``` +P x f -> f I +``` - One of the problems with non-strict languages is that it is hard to - predict in advance in which order side-effects will occur. In my program - I used a monadic IO structure like that used by the programming language - Haskell; this allows one to write programs that manipulate external - state in a manner remarkably similar to imperative programming languages - like C. An examination of my program should provide an illustration of - how well this technique works in practice. (In particular, I used the - CPS form of the IO monad from page 6 of "Imperative Functional - Programming".) +with a side-effect. - The `Y' combinator is used for implementing recursive functions. It has - the evaluation rule - Y f -> f (Y f) - so that it can be used to call a function with itself as an argument. - For example, if I had the appropriate arithmetic operators defined, I - could write a factorial function in the lambda calculus like this: - Y \f\n((= n 0) 1 (* n (f (- n 1)))) +The `G` combinator just reads a character from stdin then calls its +argument as a function with the appropriate `E` combinator as an +argument, i.e. - OFL provides a facility for naming expressions so that they can be used - more than once without writing them in full. A definition must be written - on one line in the form `l name b expression' where `l' is short for - "let" and `b' is short for "be". Names must be more than one character - long. A complete OFL program starts off by defining the primitives it - will use with likes of the form `p (S)' etc., then goes on to define the - names it will use, and finishes off with the main expression followed by - a single `e' short for "end". OFL expressions must use the minimum - number of brackets needed to be unambiguous, except that the whole - expression must be surrounded by brackets. +``` +G f -> f E(c) +``` - OFL has a standard library which adds another five combinators to the - basic eight. These combinators provide greater scope for optimisation - when translating an expression from the lambda calculus to combinators, - and therefore more compact programs. Their evaluation rules are: +with a side-effect. - B f g x -> f (g x) - C f g x -> (f x) g - BB c f g x -> c (f (g x)) - CC c f g x -> c (f x) g - SS c f g x -> c (f x) (g x) +One of the problems with non-strict languages is that it is hard to +predict in advance in which order side-effects will occur. In my program +I used a monadic IO structure like that used by the programming language +Haskell; this allows one to write programs that manipulate external +state in a manner remarkably similar to imperative programming languages +like C. An examination of my program should provide an illustration of +how well this technique works in practice. (In particular, I used the +CPS form of the IO monad from page 6 of "Imperative Functional +Programming".) - I used them to help fit my program into the required space; unfortunately - I couldn't fit the version that fully optimises the lambda expressions - it reads into the required space. The complete optimisation rules - including the ones it doesn't use are: +The `Y` combinator is used for implementing recursive functions. It has +the evaluation rule - S (K p) I -> p - S (K p) (K r) -> K ( p r ) - S (K p) (B r s) -> BB p r s - S (K p) r -> B p r - S (B p q) (K r) -> CC p q r - S p (K r) -> C p r - S (B p q) r -> SS p q r - S p r -> S p r +``` +Y f -> f (Y f) +``` + +so that it can be used to call a function with itself as an argument. +For example, if I had the appropriate arithmetic operators defined, I +could write a factorial function in the lambda calculus like this: + +``` +Y \f\n((= n 0) 1 (* n (f (- n 1)))) +``` + +`OFL` provides a facility for naming expressions so that they can be used +more than once without writing them in full. A definition must be written +on one line in the form `l name b expression` where `l` is short for +"let" and `b` is short for "be". Names must be more than one character +long. A complete `OFL` program starts off by defining the primitives it +will use with likes of the form `p (S)` etc., then goes on to define the +names it will use, and finishes off with the main expression followed by +a single `e` short for "end". `OFL` expressions must use the minimum +number of brackets needed to be unambiguous, except that the whole +expression must be surrounded by brackets. + +`OFL` has a standard library which adds another five combinators to the +basic eight. These combinators provide greater scope for optimisation +when translating an expression from the lambda calculus to combinators, +and therefore more compact programs. Their evaluation rules are: + +``` +B f g x -> f (g x) +C f g x -> (f x) g +BB c f g x -> c (f (g x)) +CC c f g x -> c (f x) g +SS c f g x -> c (f x) (g x) +``` + +I used them to help fit my program into the required space; unfortunately +I couldn't fit the version that fully optimises the lambda expressions +it reads into the required space. The complete optimisation rules +including the ones it doesn't use are: + +``` +S (K p) I -> p +S (K p) (K r) -> K ( p r ) +S (K p) (B r s) -> BB p r s +S (K p) r -> B p r +S (B p q) (K r) -> CC p q r +S p (K r) -> C p r +S (B p q) r -> SS p q r +S p r -> S p r +``` + +### The implementation of `OFL` + +Although `OFL` has completely different syntax and semantics to C, all you +need to compile `OFL` programs is a C compiler and a header file (which in +my entry to the competition has been included in-line). The header file +implements a two-pass optimising compiler which produces a representation +of the program that is then interpreted. + +The first pass of the compiler is implemented via the C preprocessor. It +implements one optimisation, namely function in-lining. Unfortunately, +this optimisation always increases object code size and execution time. +The opposite optimisation, common sub-expression elimination, (which +would offer improvements in code size and execution time) has not been +implemented. The output of this pass is a C program that may be compiled +by a normal C compiler. + +The second pass is performed by the initialisation phase of the C +program. It builds a data structure representing the abstract syntax +tree of the program. + +The program is then executed by an interpreter. This operates by +performing manipulations on the AST that correspond to the evaluation +rules of the combinators that I described above. + +The first 54 lines of the program are mostly the interpreter; the next 8 +lines are pass one of the compiler; the next nine declare the `OFL` +primitives; the next five define the `OFL` standard library; and the rest +implement the application described in the first part of this document. +This part of the program is transformed into the second pass of the +compiler by the first pass of the compiler. + +The first pass of the compiler relies on some magic macros that expand +in a mutually-overlapping and almost recursive way in order to +perpetrate a complete change of syntax. Interestingly enough, if I +hadn't used the same identifier for more than one thing in various +places in the program this transformation would work with old-style cpp +as well and ANSI cpp. It expands the program from about 2.2KB to about +740KB. The resulting code does some tricky stuff to build a data +structure of the same form as the code itself. + +The interpreter is written in fairly straightforward C, although it is +highly compressed. The C itself is written in a fairly functional style, +in that every function consists of a single expression. In the tradition +of functional programming languages it assumes that memory is infinite +and so never frees anything. It also assumes that the C compiler +implements the tail recursion optimisation, which is probably not true. - The implementation of OFL - ========================= +### References - Although OFL has completely different syntax and semantics to C, all you - need to compile OFL programs is a C compiler and a header file (which in - my entry to the competition has been included in-line). The header file - implements a two-pass optimising compiler which produces a representation - of the program that is then interpreted. +I used these references in the course of writing this program and they +explain some of the ideas behind it in more detail. Arthur Norman (one +of the authors of the first paper) did a lot to enthuse me about this +topic. - The first pass of the compiler is implemented via the C preprocessor. It - implements one optimisation, namely function in-lining. Unfortunately, - this optimisation always increases object code size and execution time. - The opposite optimisation, common sub-expression elimination, (which - would offer improvements in code size and execution time) has not been - implemented. The output of this pass is a C program that may be compiled - by a normal C compiler. +Clarke, T. J. W., et al., 1980. SKIM - the S, K, I Reduction Machine. +Proceedings of the 1980 ACM LISP Conference, pp. 128-135. - The second pass is performed by the initialisation phase of the C - program. It builds a data structure representing the abstract syntax - tree of the program. +Curry, H. B. and Feys, R., 1958. Combinatory Logic, Vol. 1. +North-Holland. - The program is then executed by an interpreter. This operates by - performing manipulations on the AST that correspond to the evaluation - rules of the combinators that I described above. +Gordon, M. J. C., 1988. Programming Language Theory and its +Implementation. Prentice-Hall. - The first 54 lines of the program are mostly the interpreter; the next 8 - lines are pass one of the compiler; the next nine declare the OFL - primitives; the next five define the OFL standard library; and the rest - implement the application described in the first part of this document. - This part of the program is transformed into the second pass of the - compiler by the first pass of the compiler. +Peterson, J, et al., 1997. Report on the Programming Language Haskell, +version 1.4. - The first pass of the compiler relies on some magic macros that expand - in a mutually-overlapping and almost recursive way in order to - perpetrate a complete change of syntax. Interestingly enough, if I - hadn't used the same identifier for more than one thing in various - places in the program this transformation would work with old-style cpp - as well and ANSI cpp. It expands the program from about 2.2KB to about - 740KB. The resulting code does some tricky stuff to build a data - structure of the same form as the code itself. +Peyton Jones, S. L., 1987. The implementation of Functional +Programming Languages, Chapters 2, 11, 12, 16. Prentice-Hall. - The interpreter is written in fairly straightforward C, although it is - highly compressed. The C itself is written in a fairly functional style, - in that every function consists of a single expression. In the tradition - of functional programming languages it assumes that memory is infinite - and so never frees anything. It also assumes that the C compiler - implements the tail recursion optimisation, which is probably not true. +Peyton Jones, S. L., and Wadler, P., 1992. Imperative Functional +Programming. Proceedings of the ACM Symposium on the Principles of +Programming Languages 1993, pp. 71-84. +Turner, D. A., 1979. A new implementation technique for applicative +languages. Software- Practice and Experience. Vol. 9, pp. 31-49. - References - ========== +Turner, D. A., 1979. Another algorithm for bracket abstraction. Journal +of Symbolic Logic. Vol. 44, no. 2, pp. 67-270. - I used these references in the course of writing this program and they - explain some of the ideas behind it in more detail. Arthur Norman (one - of the authors of the first paper) did a lot to enthuse me about this - topic. +Wadler, P., 1990. Comprehending Monads. Proceedings of the ACM +conference on Lisp and Functional Programming, 1990. - Clarke, T. J. W., et al., 1980. SKIM - the S, K, I Reduction Machine. - Proceedings of the 1980 ACM LISP Conference, pp. 128-135. - - Curry, H. B. and Feys, R., 1958. Combinatory Logic, Vol. 1. - North-Holland. - - Gordon, M. J. C., 1988. Programming Language Theory and its - Implementation. Prentice-Hall. - - Peterson, J, et al., 1997. Report on the Programming Language Haskell, - version 1.4. - - Peyton Jones, S. L., 1987. The implementation of Functional - Programming Languages, Chapters 2, 11, 12, 16. Prentice-Hall. - - Peyton Jones, S. L., and Wadler, P., 1992. Imperative Functional - Programming. Proceedings of the ACM Symposium on the Principles of - Programming Languages 1993, pp. 71-84. - - Turner, D. A., 1979. A new implementation technique for applicative - languages. Software- Practice and Experience. Vol. 9, pp. 31-49. - - Turner, D. A., 1979. Another algorithm for bracket abstraction. Journal - of Symbolic Logic. Vol. 44, no. 2, pp. 67-270. - - Wadler, P., 1990. Comprehending Monads. Proceedings of the ACM - conference on Lisp and Functional Programming, 1990. - - Wadler, P., 1995. How to Declare an Imperative. Proceedings of the ACM - International Logic Programming Symposium, 1995. +Wadler, P., 1995. How to Declare an Imperative. Proceedings of the ACM +International Logic Programming Symposium, 1995. ## Copyright and CC BY-SA 4.0 License: diff --git a/1998/schnitzi/Makefile b/1998/schnitzi/Makefile index ea859aa34..2fc43b251 100644 --- a/1998/schnitzi/Makefile +++ b/1998/schnitzi/Makefile @@ -130,7 +130,6 @@ all: data ${TARGET} supernova deep_magic magic charon pluto ${PROG}: ${PROG}.c - @echo "NOTE: this program will crash on invalid input." ${CC} ${CFLAGS} $< -o $@ ${LIBS} # alternative executable diff --git a/1998/schnitzi/README.md b/1998/schnitzi/README.md index 37e16ae7d..8ecc3085e 100644 --- a/1998/schnitzi/README.md +++ b/1998/schnitzi/README.md @@ -4,7 +4,7 @@ Mark Schnitzius ISX Corporation 1280 West Peachtree St. Apt. 1507 Atlanta, GA 30309 -USA +US ## To build: @@ -39,7 +39,7 @@ itself in two parts which required two fixes, one for linux and further changes for macOS. He also fixed a segfault (after printing garbage) when the arg specified evaluated to 0. Thank you Cody for your assistance! -### INABIAF - it's not a bug it's a feature +### INABIAF - it's not a bug it's a feature :-) NOTE: the larger the number given to the program the longer the output becomes and quite substantially so. Doing `./schnitzi 9` will actually print 771999 @@ -71,29 +71,28 @@ instance, in this paragraph, the vowel which immediately follows entire novel (E. V. Wright's "Gadsby") in which no word contains the letter 'e'. -The IOCCC has been no stranger to this concept. Several winning -entries from years past have accomplished interesting feats while -completely avoiding the use of certain C constructs thought to -be essential (e.g. 1988's robison.c). If you have to ask why they -would do it this way, then this contest just isn't for you. +The IOCCC has been no stranger to this concept. Several winning entries from +years past have accomplished interesting feats while completely avoiding the use +of certain C constructs thought to be essential (e.g. 1988's +[robison.c](//1988/robison/robison.c)). If you have to ask why they would do it +this way, then this contest just isn't for you. -In continuing with this fine tradition, this program suggests to -the ANSI committee some new practical simplifications for the C -language. For instance, it appears that CONDITIONAL BRANCHING isn't -really necessary. So, we can do away with while, do...while, for, -if/else, switch, ?:, or anything else that might cause any kind of -nondeterministic jump in the code. There's too much uncertainty -in the world anyway. +In continuing with this fine tradition, this program suggests to the ANSI +committee some new practical simplifications for the C language. For instance, +it appears that CONDITIONAL BRANCHING isn't really necessary. So, we can do +away with `while`, `do...while`, `for`, `if`/`else`, `switch`, `?:`, or anything +else that might cause any kind of nondeterministic jump in the code. There's +too much uncertainty in the world anyway. Function parameters and return types just confuse people anyway, so get rid of them. Same with local variables. In fact, all you really -need are assignment statements, and maybe one printf() and one goto. +need are assignment statements, and maybe one `printf()` and one `goto`. This style of programming is also ideal for systems with limited memory capacity, since the function call stack never goes beyond a depth of one. -So what does it do? Give it an integer (1 < n < 27) on the command +So what does it do? Give it an integer `(1 < n < 27)` on the command line, such as ```sh @@ -102,12 +101,12 @@ line, such as The output will itself be a lipographic program, one which inputs (in this case) five numbers and prints them out sorted. It sorts -them, however, using only "if/else" statements, without arrays or +them, however, using only `if/else` statements, without arrays or looping. To see the resulting program run, redirect the output from `schnitzi` into another file, like this ```sh -schnitzi 4 > sort.c +./schnitzi 4 > sort.c ``` and then compile it. diff --git a/1998/schweikh1/README.md b/1998/schweikh1/README.md index 6035fab53..2f20085e1 100644 --- a/1998/schweikh1/README.md +++ b/1998/schweikh1/README.md @@ -1,16 +1,17 @@ # CPP Abuse - Jens Schweikhardt - DFN Network Operation Center - Schlartaeckerweg 3 (Home address) - D-71384 Weinstadt - Germany - - http://www.shuttle.de/schweikh/ +Jens Schweikhardt +DFN Network Operation Center +Schlartaeckerweg 3 (Home address) +D-71384 Weinstadt +Germany + ## To build: - make all +```sh +make all +``` [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed this for modern systems (it did not work at all). He also made it so that if a file fails to @@ -22,15 +23,22 @@ mode) being instead `5+__FILE__`. It now is `"r"`. There was also a call to `fopen()` that was wrong where the mode was instead `44+__FILE__`. Interestingly enough though this did not seem to be an issue though I cannot explain why. He notes that it works fine with `clang` as well as `gcc` (which is what is used -but in macOS - see below for alternative code - `gcc` is clang). +but in macOS - see below for alternate code - `gcc` is clang). -Additionally Cody provided an alternative version for macOS. See below for the -alternative version. Thank you Cody for your assistance! +Additionally Cody provided an alternate version for macOS. See below for the +alternate version. Thank you Cody for your assistance! -### Alternative code: + +## To run: + +```sh +./schweikh1 +``` + +### Alternate code: As noted above [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) made an -alternative version that works with macOS but there are some important notes as +alternate version that works with macOS but there are some important notes as well as a description of how it works (spoilers for the original version as well). @@ -38,7 +46,7 @@ Cody said that at least with his MacBook Pro Max with the M1 chip some header files report an unsupported architecture and unsupported compiler (error, warning). However the defines are still found okay. -For this alternative version you will need the command line tools which you can +For this alternate version you will need the command line tools which you can install like: ```sh @@ -50,7 +58,9 @@ This goes for both versions. Now the key are two magic numbers, one on a different line shortly below the string. In the original the numbers are, respectively, 44 and 46. But how does this work? Well the string is: - "0gcc -ansi -E -dM -undef %s /usr/include/%s>r\0 (" +``` +"0gcc -ansi -E -dM -undef %s /usr/include/%s>r\0 (" +``` The first number means: the length starting from 0 up through the `>`. The second number is the same starting point but up through the `\0` which is why @@ -68,10 +78,6 @@ the different command line and the different numbers. To use this version use `schweikh1.alt` instead. -## To run: - - ./schweikh1 - ## Judges' remarks: What does it do? It seems to print a list of system headers, perhaps @@ -82,7 +88,7 @@ standard headers. This code is a wonder; it's a wonder that it compiles. I wonder whether or not it should. The innovative realization that you can -use special characters, such as '\n', in #file directives alone +use special characters, such as `'\n'`, in #file directives alone merits some recognition. I've included most of the author's remarks; they're fairly thorough. @@ -95,7 +101,7 @@ compile this entry correctly. Using cc by default is not helpful most of the time on this entry, because the program has a hardcoded gcc invocation anyway. Anyone who uses egcs and has no plain gcc will need to frob the source anyway and can be expected to do the -right thing with ${CC}. So use gcc. +right thing with `${CC}`. So use gcc. ## Author's remarks @@ -107,38 +113,39 @@ When run, it is likely to uncover bugs in your system headers. The program is run without arguments. If your compiler is buggy, the most likely result is no output and/or an exit status of 1. - If Amendment One headers are missing you will see - : - gcc: /usr/include/iso646.h: No such file or directory - gcc: No input files specified - : - gcc: /usr/include/wctype.h: No such file or directory - gcc: No input files specified - : - gcc: /usr/include/wchar.h: No such file or directory - gcc: No input files specified +If Amendment One headers are missing you will see something like: + +``` +: +gcc: /usr/include/iso646.h: No such file or directory +gcc: No input files specified +: +gcc: /usr/include/wctype.h: No such file or directory +gcc: No input files specified +: +gcc: /usr/include/wchar.h: No such file or directory +gcc: No input files specified +``` Bug your vendor for an upgrade. The format of the info file is straightforward and described in the file itself. Just load it in your favorite editor. -Requirements ------------- +### Requirements + +`gcc` (the GNU C compiler) must be available at runtime. It is assumed that your +C implementation keeps headers as files in the /usr/include directory. The info +file must be readable and reside in the current working directory. The current +working directory must be writable in order to create a temporary file (which is +removed upon program termination). In case you don't have gcc at runtime, not +all is lost if your compiler or preprocessor can produce a list of defined +macros in the format output by `gcc -dM`, i.e. lines of the form `#define MACRO +value`. -Gcc (the GNU C compiler) must be available at runtime. It is assumed -that your C implementation keeps headers as files in the /usr/include -directory. The info file must be readable and reside in the current -working directory. The current working directory must be writable in -order to create a temporary file (which is removed upon program -termination). In case you don't have gcc at runtime, not all is lost -if your compiler or preprocessor can produce a list of defined macros -in the format output by gcc -dM, i.e. lines of the form -#define MACRO value Edit the source at line 55 in this case. -Background ----------- +### Background ISO C has a very strict idea of visibility of identifiers. All possible macros are explicitly enumerated. In a compliant implementation no other @@ -146,122 +153,148 @@ macros can be defined, because you could write strictly conforming programs that may fail to compile due to syntax errors: suppose `` defines `PIPE_BUF`, then the conforming - #include - #include /* <- or where the bogus macro is defined */ - #include - #define STR(x) #x - #define XSTR(x) STR(x) - int main (void) - { - int PIPE_BUF = 0; - assert (strcmp ("PIPE_BUF", XSTR (PIPE_BUF)) == 0); - return 0; - } +```c +#include +#include /* <- or where the bogus macro is defined */ +#include +#define STR(x) #x +#define XSTR(x) STR(x) +int main (void) +{ + int PIPE_BUF = 0; + assert (strcmp ("PIPE_BUF", XSTR (PIPE_BUF)) == 0); + return 0; +} +``` is expected to compile and meet the assertion. If it does not, your compiler compiles some other language than ISO C. -Why I think my program is obfuscated ------------------------------------- +### Why I think my program is obfuscated Not only is the program's purpose a thorough standard conformance -test. The source itself is a beast and has uncovered bugs in many +test, the source itself is a beast and has uncovered bugs in many C compilers. -1. The token sequence after #include can consist of pp-tokens and +1. The token sequence after `#include` can consist of pp-tokens and "are processed just as in normal text." [ISO 6.8.2] The result - must resemble one of the canonical forms, "foo.h" or . + must resemble one of the canonical forms, `"foo.h"` or ``. This lets us write things like + + ```c #define HEADER "foo.h" #include HEADER + ``` + I could not find a compiler rejecting this. However, if we're torturing the preprocessor a little more, by using token pasting, at least one compiler falls over. + + ```c #define H(x) #include H(dio) /* expands to */ + ``` + is rejected by tcc version 4.1.2, the TenDRA compiler: - "t.c", line 3: Error: - [ISO 6.8.3.3]: Invalid result for '##' operator in macro 'H'. + ``` + "t.c", line 3: Error: + [ISO 6.8.3.3]: Invalid result for '##' operator in macro 'H'. + ``` + To be honest, I don't know if the rules for pp-tokens and token pasting don't forbid what I do (and tcc is correct in rejecting it). In this case, all other compilers I tried are buggy, or the Standard itself :-) -2. The #line directive allows to set a line number, and optionally - a file name, i.e. modify __LINE__ and __FILE__. Strange things +2. The `#line` directive allows to set a line number, and optionally + a file name, i.e. modify `__LINE__` and `__FILE__`. Strange things happen if the file name contains a NUL byte -- which the Standard - allows: in #line num "file" the "file" is an s-char-sequence per + allows: in `#line num "file"` the `"file"` is an s-char-sequence per ISO 6.8.4. ISO 6.1.4 defines string literals as s-char-sequences, which may include octal escape sequences. Let's look at + + ```c #include #line 42 "foo\0bar" int main (void) { printf ("%s %d\n", __FILE__, (int)sizeof __FILE__); return 0; } - This is supposed to output 'foo 8'. Here's what happens in RL: + ``` + + This is supposed to output `'foo 8'`. Here's what happens in RL: + + ``` foo 4 gcc 2.7.2.1, lcc foo\0bar 9 tcc 4.1.2, Sunsoft cc turn "\0" into "\\0", ugh! + ``` + (I have written a bug report for gcc. Newer versions and egcs are ok.) -3. The %: and %:%: digraphs test for conformance to Amendment One. +3. The `%:` and `%:%:` digraphs test for conformance to Amendment One. Ask your local guru if C allows the same case label in the same switch statement to appear more than once. Ask him/her to think real hard. The answer will be "no". The true guru will cite a constraint in -ISO 6.6.4.2. Then make fun of the guru's answer by waving 'case __LINE__:' +ISO 6.6.4.2. Then make fun of the guru's answer by waving `case __LINE__:` under his/her nose. Easy money from a bet! Make sure your guru has no chance to use Standardese weasel words as an escape: can I have + +```c case : case : +``` + in the same switch? (Note that you need the [invisible] newline. You -can generously allow the additional constraint that no #undefs or -#defines are allowed between the two cases.) +can generously allow the additional constraint that no `#undef`s or +`#define`s are allowed between the two cases.) Lots of integer constants and string literals come into the source -via __LINE__ and __FILE__ which are redefined at various places. -Sometimes the __FILE__ contains \0 bytes; different strings or -characters are then accessed with offsets, say 10+__FILE__ or -__LINE__+__FILE__ or 2[__FILE__]. One integral constant in octal. +via `__LINE__` and `__FILE__` which are redefined at various places. +Sometimes the `__FILE__` contains `\0` bytes; different strings or +characters are then accessed with offsets, say `10+__FILE__` or +`__LINE__+__FILE__` or `2[__FILE__]`. One integral constant in octal. This makes the source and header input depend on ASCII. A few old obfuscations, like one character identifiers, not too -many macros, a goto O, "needless" assignments to satisfy lint +many macros, a `goto O`, "needless" assignments to satisfy lint with its "function value ignored" warnings. My lint has nothing to complain. -There's more whitespace in the Standard than just space, tab and -newline. In particular, there are vertical tab and formfeed that -can be used in certain places (outside of preprocessing directives, -i.e. they are not allowed from just after the # up to the final -newline. See 6.8 for details.) -On many implementations these appear as ^L and ^K. My source starts -with an extremely uncommon 32bit word consisting of ^L, ^K, % and :. -I have grepped old winning entries for ^K, none of them contains one, -so this is something new -- after 14 years of IOCCC. Be sure to have -enough paper in your printer when you make a hardcopy of the source... +There's more whitespace in the Standard than just space, tab and newline. In +particular, there are vertical tab and form-feed that can be used in certain +places (outside of preprocessing directives, i.e. they are not allowed from just +after the `#` up to the final newline. See 6.8 for details.) On many +implementations these appear as `^L` and `^K`. My source starts with an +extremely uncommon 32bit word consisting of `^L`, `^K`, `%` and `:`. I have +grepped old winning entries for ^K, none of them contains one, so this is +something new -- after 14 years of IOCCC. Be sure to have enough paper in your +printer when you make a hard copy of the source... While I'm at it, the rules state that only space, tab and newline -are ignored for the count (plus '{', '}', ';' followed by -whitespace). The mkentry.c program, however, uses isspace() which -returns nonzero for vtab and formfeed and other characters as well. +are ignored for the count (plus '`{`', '`}`', '`;`' followed by +whitespace). The mkentry.c program, however, uses `isspace()` which +returns nonzero for vtab and form-feed and other characters as well. I could have used a lot more ^K and ^L probably undetected by your counter but decided to err on the side of safety. I use a perl script to compute the character count according to the rules. The advantages of an independent clean room approach... - #!/usr/bin/perl -w - $/ = "\0"; - $_ = <>; - s/[;{}][ \t\n]/\n/g; - s/[ \t\n]+//g; - print length ($_),"\n"; +```perl +#!/usr/bin/perl -w +$/ = "\0"; +$_ = <>; +s/[;{}][ \t\n]/\n/g; +s/[ \t\n]+//g; +print length ($_),"\n"; + +``` I have tried, as suggested in the guidelines, to let the code look like ordinary C code. Apart from a few long lines I think I left the indentation like I would in RL. You should however not try to use indent on the source. The code is extremely fragile because of the -myriads of __LINE__ macros -- indenting is a sure way to break +myriads of `__LINE__` macros -- indenting is a sure way to break the program. Don't even think of maintaining that beast; I've had my share of core dumps during development :-) A test suite was used after every minor change to find out if the program still diff --git a/1998/schweikh2/README.md b/1998/schweikh2/README.md index e2cc7988e..a325a9f71 100644 --- a/1998/schweikh2/README.md +++ b/1998/schweikh2/README.md @@ -1,47 +1,55 @@ # Most Erratic Behavior - Jens Schweikhardt - DFN Network Operation Center - Schlartaeckerweg 3 (Home address) - D-71384 Weinstadt - Germany - - http://www.shuttle.de/schweikh/ +Jens Schweikhardt +DFN Network Operation Center +Schlartaeckerweg 3 (Home address) +D-71384 Weinstadt +Germany + ## To build: - make all +```sh +make all +``` NOTE: Almost every compiler is supposed to be able to accept the code in -`schweikh2.c`; try compiling `schweikh2.alt.c` to see if your compiler -is fully standard-compliant. +[schweikh2.c](schweikh2.c); try compiling [schweikh2.alt.c](schweikh2.alt.c]) to +see if your compiler is fully standard-compliant. ## To run: -To use: - ./schweikh2 - +```sh +./schweikh2 + +``` or - ./schweikh2 integer_number +```sh +./schweikh2 integer_number +``` ## Try: - ./schweikh2 5 - ./schweikh2 5 +```sh +./schweikh2 5 +./schweikh2 5 - ./schweikh2 - 5 +./schweikh2 +5 +``` What is the difference here? What happens if you don't put in any number like the below? - ./schweikh2 - +```sh +./schweikh2 + +``` ## Judges' remarks: @@ -55,39 +63,52 @@ entry correctly. At the time this hint file was written, some gcc and egcs implementations ran into problem when building the original entry: - make schweikh2.alt +```sh +make schweikh2.alt +``` This program often will produce an error of the form: - gcc -ansi schweikh2.alt.c -o schweikh2.alt - as: Error: cca00NzV.s, line 58: Missing " at end of string - " - as: Error: cca00NzV.s, line 58: malformed statement - *** Error code 1 (bu21) +``` +gcc -ansi schweikh2.alt.c -o schweikh2.alt +as: Error: cca00NzV.s, line 58: Missing " at end of string + " +as: Error: cca00NzV.s, line 58: malformed statement +*** Error code 1 (bu21) +``` because the line: - ??=line 10 ONE(O(1,1,2,6,0,6)) +```c +??=line 10 ONE(O(1,1,2,6,0,6)) +``` turns into the line: - # 9 "01\012" +```c +# 9 "01\012" + +``` which causes gcc to give to the assembler the following two lines: - .stabs "whey.c - ",132,0,0,Ltext1 +```asm +.stabs "whey.c +",132,0,0,Ltext1 +``` -and the lone " after the #.file line results in an assembler syntax error. +and the lone `"` after the `#.file` line results in an assembler syntax error. In some cases one must compile using `gcc -g`: - make schweikh2.alt CFLAGS=-g +```sh +make schweikh2.alt CFLAGS=-g +``` to trigger this error. And with the proper text beyond the `\012`, it may be possible to have -all kinds of fun adding `inline assembly` via #line directives. :-) +all kinds of fun adding `inline assembly` via `#line` directives. :-) For extra credit: If your compiler has this bug, transform the line in the C @@ -97,18 +118,17 @@ the program will compile. If you are able to do the above, try adding assembly instructions so that it will compile, execute and do something interesting. -If you succeed in doing this (especially on FreeBSD, Linux or Sparc), +If you succeed in doing this (especially on FreeBSD, Linux or SPARC), email the author for a free pat on the back. -NOTE: the author submitted the program as yarng so when trying the examples +NOTE: the author submitted the program as `yarng` so when trying the examples below change `yarng` to `./schweikh2`. ## Author's remarks: -What this program does ----------------------- +### What this program does -My entry is a yarng, which stands for, you guessed it, yet another +My entry is a `yarng`, which stands for, you guessed it, yet another random number generator, and is pronounced 'yawn' due to its incredible speed. Seriously, it exploits the randomness of quantum mechanical events that build up the hardware as well as some other @@ -120,7 +140,7 @@ non-deterministic factors. Here's how it works: 4. while some other counter is not zero, go to 1) 5. exit -The yarng therefore produces output at a rate of 1 baud. The number of +The `yarng` therefore produces output at a rate of 1 baud. The number of bits may be specified by an argument and defaults either to `UINT_MAX` (least likely) or `UINT_MAX+1` (most likely). Extra credit: why the different values? How long would you need for an empirical test? @@ -128,19 +148,18 @@ different values? How long would you need for an empirical test? For example: ```sh -$ yarng 32 +$ ./yarng 32 10111001010101110110010101001111 -$ yarng 5 +$ ./yarng 5 10011 ``` -Why I think this is obfuscated ------------------------------- +### Why I think this is obfuscated - Ever seen a 'do for ... while' loop? -- I avoided 'int' like the plague. Instead I used storage class specifiers -(register, auto) to get implicit int. The Standard allows implicit int even in +- I avoided `int` like the plague. Instead I used storage class specifiers +(`register`, `auto`) to get implicit int. The Standard allows implicit int even in casts as you can see in `(void(*)(register))main`. Where implicit int is impossible, like in the `int main` declaration I have int split across two lines. All indent programs I use insert space at the beginning of the @@ -148,7 +167,7 @@ continuation line and thereby introduce a syntax error. - `main` (ab)used as a signal handler. Shocking. Yeah, this leads to undefined behaviour. I have yet to see a system where it does not work. If it doesn't work -for you, I'd appreciate if you mail me about it. Uh-oh, schweikh did it, +for you, I'd appreciate if you mail me about it. Uh-oh, Schweikh did it, uttered "Works for me". Don't quote me on that! - Even if you know how the program works, you just can't predict the output. @@ -159,7 +178,7 @@ uttered "Works for me". Don't quote me on that! preprocessor directive does the trick. But saying `#line 10 "01\n"` is a little lame and I came up with `??=line 10 ONE(O(1,1,2,6,0,6))`. -- `__LINE__` is used as the signal number argument to signal(). If indenting or +- `__LINE__` is used as the signal number argument to `signal()`. If indenting or other editing changes the number of lines the program is likely to be killed after one second... Thanks to POSIX for specifying SIGALRM as 14. You're SOL if your system does not conform. Get a real OS. @@ -175,7 +194,7 @@ this line and prepare for a core dump. and as a plain identifier in `main`'s parameters. The rule is that whenever `ONE` is followed by `(` it must be the macro. -- A quote from Kernighan and Plauger, "The Elements of Programming Style", 2nd +- A quote from Kernighan and Plauger, _The Elements of Programming Style_, 2nd Ed., page 21: "A useful way to decide if some piece of code is clear or not is the 'telephone test.' If someone could understand your code when read aloud over the telephone, it's clear enough. If not then it needs rewriting." Now try @@ -184,8 +203,7 @@ the telephone test for 'one = zero = atoi (ONE[zero-1])'. - Don't you love the aesthetics of symmetry: `write (1, 1+__FILE__+1, 1)` (telephone test this as well; is it 1, One, ONE, one? Maybe won?). -Where does the randomness come from? ------------------------------------- +### Where does the randomness come from? Each bit obviously depends on the number of times the loop body is executed between two calls of the signal handler. But what determines @@ -196,24 +214,24 @@ this number? - On multitasking OS's: The total time the process is scheduled to run between successive invocations of the signal handler. -How about the randomness of the yarng? To measure these properties I +How about the randomness of the `yarng`? To measure these properties I counted the number of bit sequences and compared them to what I would expect from a generator with uniform distribution (all sequences equally likely to occur). -It is interesting to note that yarng's maximum deviations are less -than or equal to rand()'s. Randomness however tends to degrade under +It is interesting to note that `yarng`'s maximum deviations are less +than or equal to `rand()`'s. Randomness however tends to degrade under high load averages on my system (Linux). This could be avoided by allowing the process one second of execution time instead of wall clock time (using the `SIGVTALRM` sent by the virtual timer instead of `SIGALRM`). -I'm not surprised. Yarng in the end depends on fluctuations of the +I'm not surprised. `Yarng` in the end depends on fluctuations of the electrical field and the heat distribution in the oscillators, the implementation and state of the scheduling algorithm, the system load, number and temporal distribution of asynchronous events and last but not least the phase of the moon. God _does_ play dice. -Type yarng and watch Him roll. +Type `yarng` and watch Him roll. ## Copyright and CC BY-SA 4.0 License: diff --git a/1998/schweikh3/.gitignore b/1998/schweikh3/.gitignore index fc8e75c24..30f4eadf5 100644 --- a/1998/schweikh3/.gitignore +++ b/1998/schweikh3/.gitignore @@ -1 +1,5 @@ schweikh3 +file1 +file2 +file3 +file4 diff --git a/1998/schweikh3/README.md b/1998/schweikh3/README.md index 976ff03d5..a2cc16e9b 100644 --- a/1998/schweikh3/README.md +++ b/1998/schweikh3/README.md @@ -1,203 +1,229 @@ # Most Space Efficient - Jens Schweikhardt - DFN Network Operation Center - Schlartaeckerweg 3 (Home address) - D-71384 Weinstadt - Germany - - http://www.shuttle.de/schweikh/ +Jens Schweikhardt +DFN Network Operation Center +Schlartaeckerweg 3 (Home address) +D-71384 Weinstadt +Germany + ## To build: - make all +```sh +make all +``` -## To run; +## To run: If "dir" is the directory (or a directory tree) where you keep all your favorite pictures off the Internet or from `alt.binaries.pictures.*`, do - find dir -type f -print | ./schweikh3 +```sh +find dir -type f -print | ./schweikh3 +``` + +Maybe you will not need to buy another 10 Gb disk to store them. :-) ## Try: If you're in this winning entry's directory: - find . -type f -print | ./schweikh3 +```sh +find . -type f -print | ./schweikh3 +``` Notice that the tool finds a duplicate file, that of the man page. ## Judges' remarks: - Maybe you will not need to buy another 10 Gb disk to store them. :-) - Also Try: +Try this: - cp schweikh3 file1 - cp schweikh3 file2 - cp schweikh3.c file3 - ln file3 file4 +```sh +cp schweikh3 file1 +cp schweikh3 file2 +cp schweikh3.c file3 +ln file3 file4 - ls -1 file? | ./schweikh3 +find . -type f -name 'file?' | ./schweikh3 +``` - NOTE: this program is not as smart as to detect identity of JPEG - files with the same picture but with different compression levels. +This program is not as smart as to detect identity of JPEG files with the same +picture but with different compression levels. On the other hand compression can +make it thing look/sound/feel different so these probably aren't duplicates +anyway. :-) - NOTE: Some non-gcc compilers that are not fully ANSI standard do - not compile this entry correctly. +NOTE: Some non-gcc compilers that are not fully ANSI standard do not compile +this entry correctly. ## Author's remarks - The source is expected to conform to IEEE Std 1003.1-1990 ("POSIX"). - Thank God the IEEE does not standardize a coding style... +The source is expected to conform to IEEE Std 1003.1-1990 ("POSIX"). +Thank God the IEEE does not standardize a coding style... - What this program does - ---------------------- +### What this program does - This is best explained in the man page. The troff source for this - man page can be found in the file samefile.1. - - SAMEFILE(1) User Manuals SAMEFILE(1) +This is best explained in the man page. The troff source for this +man page can be found in the file samefile.1. To render try: `man +./samefile.1`. Otherwise: - NAME - samefile - find identical files +**SAMEFILE(1) User Manuals SAMEFILE(1)** - SYNOPSIS - samefile - DESCRIPTION - samefile reads a list of file names (one file name per - line) from stdin. For each file name pair with identical - contents, a line consisting of six tab separated fields is - output: The size in bytes, two file names, the character - ``='' if the two files are on the same device, ``X'' oth- - erwise, and the link counts of the two files. The output - is sorted in reverse order by size. +**NAME** - samefile uses two stages to give optimum performance. + **samefile** - find identical files - In the first stage, all non-plain files are silently - ignored (directories, devices, FIFOs, sockets, symbolic - links) as well as files for which stat(2) or open(2) - fails. The result of the first stage (the file names) is - written into a binary tree with one node for every file - size. Each node is in turn a linked list of file names - along with inode and device information. It is also at - this first stage where checks for hard links are done. - For any inode only one filename will be added to the - binary tree. +**SYNOPSIS** - In the second stage all files having the same size are - compared against each other. The rules of mathematical - logic are applied to reduce work and output noise: if - files A, B, and C have the same size and samefile finds - that A = B and A = C then it will not compare B against C - (and will not output a line for B and C) but only for A = - B and A = C. The algorithm will detect equality across - arbitrarily long chains. Note however, that because only - the first filename per inode gets into the first stage, - the output for a group of identical files with different - inode numbers is also minimized. Suppose you have six - identical files of size 100 in an inode group consisting - of the three inodes with numbers 10, 20 and 30: + **./samefile** +**DESCRIPTION** + +**samefile** reads a list of file names (one file name per +line) from stdin. For each file name pair with identical +contents, a line consisting of six tab separated fields is +output: The size in bytes, two file names, the character +`=` if the two files are on the same device, `X` otherwise, +and the link counts of the two files. The output +is sorted in reverse order by size. + +samefile uses two stages to give optimum performance. + +In the first stage, all non-plain files are silently +ignored (directories, devices, FIFOs, sockets, symbolic +links) as well as files for which `stat(2)` or `open(2)` +fails. The result of the first stage (the file names) is +written into a binary tree with one node for every file +size. Each node is in turn a linked list of file names +along with inode and device information. It is also at +this first stage where checks for hard links are done. +For any inode only one filename will be added to the +binary tree. + +In the second stage all files having the same size are +compared against each other. The rules of mathematical +logic are applied to reduce work and output noise: if +files A, B, and C have the same size and samefile finds +that A = B and A = C then it will not compare B against C +(and will not output a line for B and C) but only for A = +B and A = C. The algorithm will detect equality across +arbitrarily long chains. Note however, that because only +the first filename per inode gets into the first stage, +the output for a group of identical files with different +inode numbers is also minimized. Suppose you have six +identical files of size 100 in an inode group consisting +of the three inodes with numbers 10, 20 and 30: + +```sh $ ls -i # output edited for readability: 10 file1 20 file4 30 file6 10 file2 20 file5 10 file3 - $ ls | samefile + $ ls | ./samefile 100 file1 file4 = 3 2 100 file1 file6 = 3 1 +``` - The sum of the sizes in the first column is the amount of - disk space you could gain by making all 6 files links to - only one file or remove all but one of the files. To be - precise, disk space is allocated in blocks - you will - probably gain two blocks here, rather than 200 bytes. - Note that it is not enough to just remove file4 and file6 - (you would gain only 100 bytes because file5 still - exists.) +The sum of the sizes in the first column is the amount of +disk space you could gain by making all 6 files links to +only one file or remove all but one of the files. To be +precise, disk space is allocated in blocks - you will +probably gain two blocks here, rather than 200 bytes. +Note that it is not enough to just remove `file4` and `file6` +(you would gain only 100 bytes because `file5` still +exists.) - LIMITATIONS - Samefile was written with no limits in mind. The number of - input lines is unlimited. The size of the actual files is - only limited by available virtual memory needed to compare - one pair of files. The only hard limit is the constraint - that there should not be more than about 8192 files having - the same size. Experience has shown that there are rarely - more than a couple dozen files of the same size. +**LIMITATIONS** - EXAMPLES - For everybody: - What are the duplicates under my home directory? +`samefile` was written with no limits in mind. The number of +input lines is unlimited. The size of the actual files is +only limited by available virtual memory needed to compare +one pair of files. The only hard limit is the constraint +that there should not be more than about 8192 files having +the same size. Experience has shown that there are rarely +more than a couple dozen files of the same size. - $ find $HOME | samefile +**EXAMPLES** - For the sysadmin folks: - Report all duplicate files under /usr larger than 16k: +For everybody: - $ find /usr -size +16384c -a -type f | samefile +What are the duplicates under my home directory? - For the ftp and WWW admins: - How much space is wasted below our site's /pub directory? +```sh + $ find $HOME | ./samefile +``` - $ find /pub -type f | samefile | awk '{sum += $1} END {print sum}' +For the sysadmin folks: + +Report all duplicate files under /usr larger than 16k: + +```sh + $ find /usr -size +16384c -a -type f | ./samefile +``` + +For the ftp and WWW admins: +How much space is wasted below our site's /pub directory? + +```sh + $ find /pub -type f | samefile | awk '{sum += $1} END {print sum}' +``` +**EXIT STATUS** - EXIT STATUS - If samefile runs out of memory the exit status is 1, zero - otherwise. +If `samefile` runs out of memory the exit status is 1, zero +otherwise. - SEE ALSO - find(1), ln(1), rm(1) +**SEE ALSO** +`find(1)`, `ln(1)`, `rm(1)` - Why I think it is obfuscated - ---------------------------- + +### Why I think it is obfuscated - - the code is commented but this gives only an *extremely* faint clue. - - the layout does not reflect the program structure, or does it? - - The data structure the program builds is an ordered binary tree - where each node consists of a linked list. This is probably too - heavy to comprehend for N percent of all programmers ;-) - - The tree is built and traversed by recursive function calls. - - Why does this program look at dev_t and ino_t? Heavy wizardry. - - Can you find out how the algorithm works that detects identity - of files across arbitrarily long chains? In my private unobfuscated - source there are 17 lines describing just that. A classical case for - the well known /* You're not supposed to understand this */ comment. - - Would Dijkstra consider this goto harmful? - - The only string literal is split in more than a dozen substrings - - For the task at hand the code is pretty terse. Some dynamic memory - is even freed as soon as it's no longer needed. I have tried to - make the preprocessor directives as short as possible. This means - no spaces after #include and no spaces after some of the macro - names. +- The code is commented but this gives only an *extremely* faint clue. +- The layout does not reflect the program structure, or does it? +- The data structure the program builds is an ordered binary tree + where each node consists of a linked list. This is probably too + heavy to comprehend for N percent of all programmers ;-) +- The tree is built and traversed by recursive function calls. +- Why does this program look at `dev_t` and `ino_t`? Heavy wizardry. +- Can you find out how the algorithm works that detects identity + of files across arbitrarily long chains? In my private unobfuscated + source there are 17 lines describing just that. A classical case for + the well known `/* You're not supposed to understand this */` comment. +- Would Dijkstra consider this goto harmful? +- The only string literal is split in more than a dozen substrings +- For the task at hand the code is pretty terse. Some dynamic memory + is even freed as soon as it's no longer needed. I have tried to + make the preprocessor directives as short as possible. This means + no spaces after #include and no spaces after some of the macro + names. - Are you an algorithms guru? If so you should know why the output - appears sorted without any use of qsort() or system("sort"). +Are you an algorithms guru? If so you should know why the output +appears sorted without any use of `qsort()` or `system("sort")`. - Rewrite (hah!) the program to use memory mapping of files instead - of read(). Does this affect performance noticeably? +Rewrite (hah!) the program to use memory mapping of files instead +of `read()`. Does this affect performance noticeably? - It's easy to write a script that takes samefile's output and - hardlinks (or symlinks) identical files. Writing such a script is - left as an exercise for the deobfuscator. +It's easy to write a script that takes `samefile`'s output and +hard links (or symlinks) identical files. Writing such a script is +left as an exercise for the deobfuscator. - When you run samefile on some directory tree, try to estimate - how much you think it will find. Is the actual result anywhere - near your estimate? How many copies of the GPL COPYING file - are there on your filesystems? :-) +When you run `samefile` on some directory tree, try to estimate +how much you think it will find. Is the actual result anywhere +near your estimate? How many copies of the GPL COPYING file +are there on your filesystems? :-) - In the remote event that the input has more than 8192 files with - the same size (on systems where sizeof (char *) == 4, or 4096 when - sizeof (char *) == 8), increase the manifest constant 32767 on line - 31. +In the remote event that the input has more than 8192 files with +the same size (on systems where `sizeof (char *) == 4`, or 4096 when +`sizeof (char *) == 8`), increase the manifest constant 32767 on line +31. ## Copyright and CC BY-SA 4.0 License: diff --git a/1998/tomtorfs/README.md b/1998/tomtorfs/README.md index 976056c90..453113765 100644 --- a/1998/tomtorfs/README.md +++ b/1998/tomtorfs/README.md @@ -1,105 +1,136 @@ # Best Self-Documenting - Tom Torfs - De Nayer Instituut - Cuperuslei 12 (home address) - 2220 Heist-op-den-Berg - Belgium - - http://members.xoom.com/tomtorfs +Tom Torfs +De Nayer Instituut +Cuperuslei 12 (home address) +2220 Heist-op-den-Berg +Belgium + ## To build: - make all +```sh +make all +``` -## To run +## To run: - ./tomtorfs tomtorfs.c 32 04C11DB7 1 FFFFFFFF FFFFFFFF +```sh +./tomtorfs tomtorfs.c 32 04C11DB7 1 FFFFFFFF FFFFFFFF +``` -## Judges' remarks +## Try: - Also try: +```sh +echo "abscond conferrable" > file.A +echo "adorn condolence" > file.B +echo "adorn condolence too" > file.C +./tomtorfs file.A 32 04C11DB7 1 FFFFFFFF FFFFFFFF +./tomtorfs file.B 32 04C11DB7 1 FFFFFFFF FFFFFFFF +./tomtorfs file.C 32 04C11DB7 1 FFFFFFFF FFFFFFFF +``` - echo "abscond conferrable" > file.A - echo "adorn condolence" > file.B - echo "adorn condolence too" > file.C - ./tomtorfs file.A 32 04C11DB7 1 FFFFFFFF FFFFFFFF - ./tomtorfs file.B 32 04C11DB7 1 FFFFFFFF FFFFFFFF - ./tomtorfs file.C 32 04C11DB7 1 FFFFFFFF FFFFFFFF +## Judges' remarks: - If you don't believe the program is correct, try and compare the output - of the program with the value of CRC computed by PKZIP or any other - archiver that uses the CRC-32 algorithm. +If you don't believe the program is correct, try and compare the output +of the program with the value of CRC computed by PKZIP or any other +archiver that uses the CRC-32 algorithm. -## Author's remarks +## Author's remarks: - Usage: - crc filename bitwidth polynom reflected init xor +``` +Usage: +./tomtorfs filename bitwidth polynom reflected init xor - filename : file to calculate the CRC of - bitwidth : width of the CRC in bits (decimal) - polynom : polynomial used for the CRC (hexadecimal) - reflected : 0 if the CRC is not reflected, 1 if it is - init : initial value for the CRC (hexadecimal) - xor : value to xor the final CRC with (hexadecimal) +filename : file to calculate the CRC of +bitwidth : width of the CRC in bits (decimal) +polynom : polynomial used for the CRC (hexadecimal) +reflected : 0 if the CRC is not reflected, 1 if it is +init : initial value for the CRC (hexadecimal) +xor : value to xor the final CRC with (hexadecimal) +``` - Examples: +### Examples - CRC-16: crc filename 16 1021 0 FFFF 0000 - CRC-32: crc filename 32 04C11DB7 1 FFFFFFFF FFFFFFFF - XMODEM: crc filename 16 8408 1 0000 0000 - ARC: crc filename 16 8005 1 0000 0000 +#### CRC-16: - Portability notes: +```sh +./tomtorfs filename 16 1021 0 FFFF 0000 +``` - The program assumes CHAR_BIT==8. Results are undefined if - bitwidth > sizeof(unsigned long) * 8. It is also assumed - that EOF is -1 and 1 is a valid exit value to indicate - failure (replace them with EOF resp. EXIT_FAILURE if the - assumptions are false). Otherwise ANSI/ISO C. - No special build options required. +#### CRC-32: - Special notes: - Count the number of non-whitespace characters in the source - file to find out what dark force drove me to write this ;-). +```sh +./tomtorfs filename 32 04C11DB7 1 FFFFFFFF FFFFFFFF +``` - Spoiler: +#### XMODEM: - First of all, if you run a C beautifier on the program - (thereby of course losing the nice code shape I worked - so hard on ;-) the code will become a bit more readable. +```sh +./tomtorfs filename 16 8408 1 0000 0000 - The variable names are not very descriptive. They have the - following meanings: - a = argc - A = argv - b = array of unsigned long variables - b[0] = bit-width of the CRC (argv[2]) - b[1] = CRC polynomial (argv[3]) - b[2] = nonzero if CRC is reflected (argv[4]) - b[3] = initial value of CRC (argv[5]) - b[4] = value final CRC is XORed with (argv[6]) - b[5] = CRC value - b[6] = byte from file - b[7] = counter - B = FILE * through which the file argv[1] is opened - C = typedef for unsigned long +``` - The first for loop simply reads the command-line arguments - in the b[] array. The third parameter to strtoul() causes - all arguments to be in base-16 (hex) except the first one, - which will be in base-10 (decimal). +#### ARC: - The rest of the program "simply" calculates the crc in b[5] - and then prints it to stdout. The bit reflection loops may - appear a bit tricky at first, but if you have a good look - at them they should become obvious also. +```sh +./tomtorfs filename 16 8005 1 0000 0000 +``` - Acknowledgments: +### Portability notes - Ross N. Williams, whose CRC guide was very useful to me - for writing this. You can find it as CRC.TXT in Snippets. +The program assumes `CHAR_BIT==8`. Results are undefined if `bitwidth > +sizeof(unsigned long) * 8`. It is also assumed that `EOF` is `-1` and `1` is a +valid exit value to indicate failure (replace them with `EOF` resp. +`EXIT_FAILURE` if the assumptions are false). Otherwise ANSI/ISO C. + +No special build options required. + +### Special notes + +Count the number of non-whitespace characters in the source +file to find out what dark force drove me to write this ;-). + +### Spoiler + +First of all, if you run a C beautifier on the program (thereby of course losing +the nice code shape I worked so hard on ;-) ) the code will become a bit more +readable. + +The variable names are not very descriptive. They have the +following meanings: + +``` +a = argc +A = argv +b = array of unsigned long variables + b[0] = bit-width of the CRC (argv[2]) + b[1] = CRC polynomial (argv[3]) + b[2] = nonzero if CRC is reflected (argv[4]) + b[3] = initial value of CRC (argv[5]) + b[4] = value final CRC is XORed with (argv[6]) + b[5] = CRC value + b[6] = byte from file + b[7] = counter +B = FILE * through which the file argv[1] is opened +C = typedef for unsigned long +``` + +The first for loop simply reads the command-line arguments +in the `b[]` array. The third parameter to `strtoul()` causes +all arguments to be in base-16 (hex) except the first one, +which will be in base-10 (decimal). + +The rest of the program "simply" calculates the CRC in `b[5]` +and then prints it to stdout. The bit reflection loops may +appear a bit tricky at first, but if you have a good look +at them they should become obvious also. + +### Acknowledgments: + +Ross N. Williams, whose CRC guide was very useful to me +for writing this. You can find it in [crc.txt](crc.txt). ## Copyright and CC BY-SA 4.0 License: diff --git a/1998/tomtorfs/crc.txt b/1998/tomtorfs/crc.txt new file mode 100644 index 000000000..ca92e1b86 --- /dev/null +++ b/1998/tomtorfs/crc.txt @@ -0,0 +1,2069 @@ + +A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS +================================================== +"Everything you wanted to know about CRC algorithms, but were afraid +to ask for fear that errors in your understanding might be detected." + +Version : 3. +Date : 19 August 1993. +Author : Ross N. Williams. +Net : ross@guest.adelaide.edu.au. +FTP : ftp.adelaide.edu.au/pub/rocksoft/crc_v3.txt +Company : Rocksoft^tm Pty Ltd. +Snail : 16 Lerwick Avenue, Hazelwood Park 5066, Australia. +Fax : +61 8 373-4911 (c/- Internode Systems Pty Ltd). +Phone : +61 8 379-9217 (10am to 10pm Adelaide Australia time). +Note : "Rocksoft" is a trademark of Rocksoft Pty Ltd, Australia. +Status : Copyright (C) Ross Williams, 1993. However, permission is + granted to make and distribute verbatim copies of this + document provided that this information block and copyright + notice is included. Also, the C code modules included + in this document are fully public domain. +Thanks : Thanks to Jean-loup Gailly (jloup@chorus.fr) and Mark Adler + (me@quest.jpl.nasa.gov) who both proof read this document + and picked out lots of nits as well as some big fat bugs. + +Table of Contents +----------------- + Abstract + 1. Introduction: Error Detection + 2. The Need For Complexity + 3. The Basic Idea Behind CRC Algorithms + 4. Polynomical Arithmetic + 5. Binary Arithmetic with No Carries + 6. A Fully Worked Example + 7. Choosing A Poly + 8. A Straightforward CRC Implementation + 9. A Table-Driven Implementation +10. A Slightly Mangled Table-Driven Implementation +11. "Reflected" Table-Driven Implementations +12. "Reversed" Polys +13. Initial and Final Values +14. Defining Algorithms Absolutely +15. A Parameterized Model For CRC Algorithms +16. A Catalog of Parameter Sets for Standards +17. An Implementation of the Model Algorithm +18. Roll Your Own Table-Driven Implementation +19. Generating A Lookup Table +20. Summary +21. Corrections + A. Glossary + B. References + C. References I Have Detected But Haven't Yet Sighted + + +Abstract +-------- +This document explains CRCs (Cyclic Redundancy Codes) and their +table-driven implementations in full, precise detail. Much of the +literature on CRCs, and in particular on their table-driven +implementations, is a little obscure (or at least seems so to me). +This document is an attempt to provide a clear and simple no-nonsense +explanation of CRCs and to absolutely nail down every detail of the +operation of their high-speed implementations. In addition to this, +this document presents a parameterized model CRC algorithm called the +"Rocksoft^tm Model CRC Algorithm". The model algorithm can be +parameterized to behave like most of the CRC implementations around, +and so acts as a good reference for describing particular algorithms. +A low-speed implementation of the model CRC algorithm is provided in +the C programming language. Lastly there is a section giving two forms +of high-speed table driven implementations, and providing a program +that generates CRC lookup tables. + + +1. Introduction: Error Detection +-------------------------------- +The aim of an error detection technique is to enable the receiver of a +message transmitted through a noisy (error-introducing) channel to +determine whether the message has been corrupted. To do this, the +transmitter constructs a value (called a checksum) that is a function +of the message, and appends it to the message. The receiver can then +use the same function to calculate the checksum of the received +message and compare it with the appended checksum to see if the +message was correctly received. For example, if we chose a checksum +function which was simply the sum of the bytes in the message mod 256 +(i.e. modulo 256), then it might go something as follows. All numbers +are in decimal. + + Message : 6 23 4 + Message with checksum : 6 23 4 33 + Message after transmission : 6 27 4 33 + +In the above, the second byte of the message was corrupted from 23 to +27 by the communications channel. However, the receiver can detect +this by comparing the transmitted checksum (33) with the computer +checksum of 37 (6 + 27 + 4). If the checksum itself is corrupted, a +correctly transmitted message might be incorrectly identified as a +corrupted one. However, this is a safe-side failure. A dangerous-side +failure occurs where the message and/or checksum is corrupted in a +manner that results in a transmission that is internally consistent. +Unfortunately, this possibility is completely unavoidable and the best +that can be done is to minimize its probability by increasing the +amount of information in the checksum (e.g. widening the checksum from +one byte to two bytes). + +Other error detection techniques exist that involve performing complex +transformations on the message to inject it with redundant +information. However, this document addresses only CRC algorithms, +which fall into the class of error detection algorithms that leave the +data intact and append a checksum on the end. i.e.: + + + + +2. The Need For Complexity +-------------------------- +In the checksum example in the previous section, we saw how a +corrupted message was detected using a checksum algorithm that simply +sums the bytes in the message mod 256: + + Message : 6 23 4 + Message with checksum : 6 23 4 33 + Message after transmission : 6 27 4 33 + +A problem with this algorithm is that it is too simple. If a number of +random corruptions occur, there is a 1 in 256 chance that they will +not be detected. For example: + + Message : 6 23 4 + Message with checksum : 6 23 4 33 + Message after transmission : 8 20 5 33 + +To strengthen the checksum, we could change from an 8-bit register to +a 16-bit register (i.e. sum the bytes mod 65536 instead of mod 256) so +as to apparently reduce the probability of failure from 1/256 to +1/65536. While basically a good idea, it fails in this case because +the formula used is not sufficiently "random"; with a simple summing +formula, each incoming byte affects roughly only one byte of the +summing register no matter how wide it is. For example, in the second +example above, the summing register could be a Megabyte wide, and the +error would still go undetected. This problem can only be solved by +replacing the simple summing formula with a more sophisticated formula +that causes each incoming byte to have an effect on the entire +checksum register. + +Thus, we see that at least two aspects are required to form a strong +checksum function: + + WIDTH: A register width wide enough to provide a low a-priori + probability of failure (e.g. 32-bits gives a 1/2^32 chance + of failure). + + CHAOS: A formula that gives each input byte the potential to change + any number of bits in the register. + +Note: The term "checksum" was presumably used to describe early +summing formulas, but has now taken on a more general meaning +encompassing more sophisticated algorithms such as the CRC ones. The +CRC algorithms to be described satisfy the second condition very well, +and can be configured to operate with a variety of checksum widths. + + +3. The Basic Idea Behind CRC Algorithms +--------------------------------------- +Where might we go in our search for a more complex function than +summing? All sorts of schemes spring to mind. We could construct +tables using the digits of pi, or hash each incoming byte with all the +bytes in the register. We could even keep a large telephone book +on-line, and use each incoming byte combined with the register bytes +to index a new phone number which would be the next register value. +The possibilities are limitless. + +However, we do not need to go so far; the next arithmetic step +suffices. While addition is clearly not strong enough to form an +effective checksum, it turns out that division is, so long as the +divisor is about as wide as the checksum register. + +The basic idea of CRC algorithms is simply to treat the message as an +enormous binary number, to divide it by another fixed binary number, +and to make the remainder from this division the checksum. Upon +receipt of the message, the receiver can perform the same division and +compare the remainder with the "checksum" (transmitted remainder). + +Example: Suppose the the message consisted of the two bytes (6,23) as +in the previous example. These can be considered to be the hexadecimal +number 0617 which can be considered to be the binary number +0000-0110-0001-0111. Suppose that we use a checksum register one-byte +wide and use a constant divisor of 1001, then the checksum is the +remainder after 0000-0110-0001-0111 is divided by 1001. While in this +case, this calculation could obviously be performed using common +garden variety 32-bit registers, in the general case this is messy. So +instead, we'll do the division using good-'ol long division which you +learnt in school (remember?). Except this time, it's in binary: + + ...0000010101101 = 00AD = 173 = QUOTIENT + ____-___-___-___- +9= 1001 ) 0000011000010111 = 0617 = 1559 = DIVIDEND +DIVISOR 0000.,,....,.,,, + ----.,,....,.,,, + 0000,,....,.,,, + 0000,,....,.,,, + ----,,....,.,,, + 0001,....,.,,, + 0000,....,.,,, + ----,....,.,,, + 0011....,.,,, + 0000....,.,,, + ----....,.,,, + 0110...,.,,, + 0000...,.,,, + ----...,.,,, + 1100..,.,,, + 1001..,.,,, + ====..,.,,, + 0110.,.,,, + 0000.,.,,, + ----.,.,,, + 1100,.,,, + 1001,.,,, + ====,.,,, + 0111.,,, + 0000.,,, + ----.,,, + 1110,,, + 1001,,, + ====,,, + 1011,, + 1001,, + ====,, + 0101, + 0000, + ---- + 1011 + 1001 + ==== + 0010 = 02 = 2 = REMAINDER + + +In decimal this is "1559 divided by 9 is 173 with a remainder of 2". + +Although the effect of each bit of the input message on the quotient +is not all that significant, the 4-bit remainder gets kicked about +quite a lot during the calculation, and if more bytes were added to +the message (dividend) it's value could change radically again very +quickly. This is why division works where addition doesn't. + +In case you're wondering, using this 4-bit checksum the transmitted +message would look like this (in hexadecimal): 06172 (where the 0617 +is the message and the 2 is the checksum). The receiver would divide +0617 by 9 and see whether the remainder was 2. + + +4. Polynomical Arithmetic +------------------------- +While the division scheme described in the previous section is very +very similar to the checksumming schemes called CRC schemes, the CRC +schemes are in fact a bit weirder, and we need to delve into some +strange number systems to understand them. + +The word you will hear all the time when dealing with CRC algorithms +is the word "polynomial". A given CRC algorithm will be said to be +using a particular polynomial, and CRC algorithms in general are said +to be operating using polynomial arithmetic. What does this mean? + +Instead of the divisor, dividend (message), quotient, and remainder +(as described in the previous section) being viewed as positive +integers, they are viewed as polynomials with binary coefficients. +This is done by treating each number as a bit-string whose bits are +the coefficients of a polynomial. For example, the ordinary number 23 +(decimal) is 17 (hex) and 10111 binary and so it corresponds to the +polynomial: + + 1*x^4 + 0*x^3 + 1*x^2 + 1*x^1 + 1*x^0 + +or, more simply: + + x^4 + x^2 + x^1 + x^0 + +Using this technique, the message, and the divisor can be represented +as polynomials and we can do all our arithmetic just as before, except +that now it's all cluttered up with Xs. For example, suppose we wanted +to multiply 1101 by 1011. We can do this simply by multiplying the +polynomials: + +(x^3 + x^2 + x^0)(x^3 + x^1 + x^0) += (x^6 + x^4 + x^3 + + x^5 + x^3 + x^2 + + x^3 + x^1 + x^0) = x^6 + x^5 + x^4 + 3*x^3 + x^2 + x^1 + x^0 + +At this point, to get the right answer, we have to pretend that x is 2 +and propagate binary carries from the 3*x^3 yielding + + x^7 + x^3 + x^2 + x^1 + x^0 + +It's just like ordinary arithmetic except that the base is abstracted +and brought into all the calculations explicitly instead of being +there implicitly. So what's the point? + +The point is that IF we pretend that we DON'T know what x is, we CAN'T +perform the carries. We don't know that 3*x^3 is the same as x^4 + x^3 +because we don't know that x is 2. In this true polynomial arithmetic +the relationship between all the coefficients is unknown and so the +coefficients of each power effectively become strongly typed; +coefficients of x^2 are effectively of a different type to +coefficients of x^3. + +With the coefficients of each power nicely isolated, mathematicians +came up with all sorts of different kinds of polynomial arithmetics +simply by changing the rules about how coefficients work. Of these +schemes, one in particular is relevant here, and that is a polynomial +arithmetic where the coefficients are calculated MOD 2 and there is no +carry; all coefficients must be either 0 or 1 and no carries are +calculated. This is called "polynomial arithmetic mod 2". Thus, +returning to the earlier example: + +(x^3 + x^2 + x^0)(x^3 + x^1 + x^0) += (x^6 + x^4 + x^3 + + x^5 + x^3 + x^2 + + x^3 + x^1 + x^0) += x^6 + x^5 + x^4 + 3*x^3 + x^2 + x^1 + x^0 + +Under the other arithmetic, the 3*x^3 term was propagated using the +carry mechanism using the knowledge that x=2. Under "polynomial +arithmetic mod 2", we don't know what x is, there are no carries, and +all coefficients have to be calculated mod 2. Thus, the result +becomes: + += x^6 + x^5 + x^4 + x^3 + x^2 + x^1 + x^0 + +As Knuth [Knuth81] says (p.400): + + "The reader should note the similarity between polynomial + arithmetic and multiple-precision arithmetic (Section 4.3.1), where + the radix b is substituted for x. The chief difference is that the + coefficient u_k of x^k in polynomial arithmetic bears little or no + relation to its neighboring coefficients x^{k-1} [and x^{k+1}], so + the idea of "carrying" from one place to another is absent. In fact + polynomial arithmetic modulo b is essentially identical to multiple + precision arithmetic with radix b, except that all carries are + suppressed." + +Thus polynomical arithmetic mod 2 is just binary arithmetic mod 2 with +no carries. While polynomials provide useful mathematical machinery in +more analytical approaches to CRC and error-correction algorithms, for +the purposes of exposition they provide no extra insight and some +encumbrance and have been discarded in the remainder of this document +in favour of direct manipulation of the arithmetical system with which +they are isomorphic: binary arithmetic with no carry. + + +5. Binary Arithmetic with No Carries +------------------------------------ +Having dispensed with polynomials, we can focus on the real arithmetic +issue, which is that all the arithmetic performed during CRC +calculations is performed in binary with no carries. Often this is +called polynomial arithmetic, but as I have declared the rest of this +document a polynomial free zone, we'll have to call it CRC arithmetic +instead. As this arithmetic is a key part of CRC calculations, we'd +better get used to it. Here we go: + +Adding two numbers in CRC arithmetic is the same as adding numbers in +ordinary binary arithmetic except there is no carry. This means that +each pair of corresponding bits determine the corresponding output bit +without reference to any other bit positions. For example: + + 10011011 + +11001010 + -------- + 01010001 + -------- + +There are only four cases for each bit position: + + 0+0=0 + 0+1=1 + 1+0=1 + 1+1=0 (no carry) + +Subtraction is identical: + + 10011011 + -11001010 + -------- + 01010001 + -------- + +with + + 0-0=0 + 0-1=1 (wraparound) + 1-0=1 + 1-1=0 + +In fact, both addition and subtraction in CRC arithmetic is equivalent +to the XOR operation, and the XOR operation is its own inverse. This +effectively reduces the operations of the first level of power +(addition, subtraction) to a single operation that is its own inverse. +This is a very convenient property of the arithmetic. + +By collapsing of addition and subtraction, the arithmetic discards any +notion of magnitude beyond the power of its highest one bit. While it +seems clear that 1010 is greater than 10, it is no longer the case +that 1010 can be considered to be greater than 1001. To see this, note +that you can get from 1010 to 1001 by both adding and subtracting the +same quantity: + + 1010 = 1010 + 0011 + 1010 = 1010 - 0011 + +This makes nonsense of any notion of order. + +Having defined addition, we can move to multiplication and division. +Multiplication is absolutely straightforward, being the sum of the +first number, shifted in accordance with the second number. + + 1101 + x 1011 + ---- + 1101 + 1101. + 0000.. + 1101... + ------- + 1111111 Note: The sum uses CRC addition + ------- + +Division is a little messier as we need to know when "a number goes +into another number". To do this, we invoke the weak definition of +magnitude defined earlier: that X is greater than or equal to Y iff +the position of the highest 1 bit of X is the same or greater than the +position of the highest 1 bit of Y. Here's a fully worked division +(nicked from [Tanenbaum81]). + + 1100001010 + _______________ +10011 ) 11010110110000 + 10011,,.,,.... + -----,,.,,.... + 10011,.,,.... + 10011,.,,.... + -----,.,,.... + 00001.,,.... + 00000.,,.... + -----.,,.... + 00010,,.... + 00000,,.... + -----,,.... + 00101,.... + 00000,.... + -----,.... + 01011.... + 00000.... + -----.... + 10110... + 10011... + -----... + 01010.. + 00000.. + -----.. + 10100. + 10011. + -----. + 01110 + 00000 + ----- + 1110 = Remainder + +That's really it. Before proceeding further, however, it's worth our +while playing with this arithmetic a bit to get used to it. + +We've already played with addition and subtraction, noticing that they +are the same thing. Here, though, we should note that in this +arithmetic A+0=A and A-0=A. This obvious property is very useful +later. + +In dealing with CRC multiplication and division, it's worth getting a +feel for the concepts of MULTIPLE and DIVISIBLE. + +If a number A is a multiple of B then what this means in CRC +arithmetic is that it is possible to construct A from zero by XORing +in various shifts of B. For example, if A was 0111010110 and B was 11, +we could construct A from B as follows: + + 0111010110 + = .......11. + + ....11.... + + ...11..... + .11....... + +However, if A is 0111010111, it is not possible to construct it out of +various shifts of B (can you see why? - see later) so it is said to be +not divisible by B in CRC arithmetic. + +Thus we see that CRC arithmetic is primarily about XORing particular +values at various shifting offsets. + + +6. A Fully Worked Example +------------------------- +Having defined CRC arithmetic, we can now frame a CRC calculation as +simply a division, because that's all it is! This section fills in the +details and gives an example. + +To perform a CRC calculation, we need to choose a divisor. In maths +marketing speak the divisor is called the "generator polynomial" or +simply the "polynomial", and is a key parameter of any CRC algorithm. +It would probably be more friendly to call the divisor something else, +but the poly talk is so deeply ingrained in the field that it would +now be confusing to avoid it. As a compromise, we will refer to the +CRC polynomial as the "poly". Just think of this number as a sort of +parrot. "Hello poly!" + +You can choose any poly and come up with a CRC algorithm. However, +some polys are better than others, and so it is wise to stick with the +tried an tested ones. A later section addresses this issue. + +The width (position of the highest 1 bit) of the poly is very +important as it dominates the whole calculation. Typically, widths of +16 or 32 are chosen so as to simplify implementation on modern +computers. The width of a poly is the actual bit position of the +highest bit. For example, the width of 10011 is 4, not 5. For the +purposes of example, we will chose a poly of 10011 (of width W of 4). + +Having chosen a poly, we can proceed with the calculation. This is +simply a division (in CRC arithmetic) of the message by the poly. The +only trick is that W zero bits are appended to the message before the +CRC is calculated. Thus we have: + + Original message : 1101011011 + Poly : 10011 + Message after appending W zeros : 11010110110000 + +Now we simply divide the augmented message by the poly using CRC +arithmetic. This is the same division as before: + + 1100001010 = Quotient (nobody cares about the quotient) + _______________ +10011 ) 11010110110000 = Augmented message (1101011011 + 0000) +=Poly 10011,,.,,.... + -----,,.,,.... + 10011,.,,.... + 10011,.,,.... + -----,.,,.... + 00001.,,.... + 00000.,,.... + -----.,,.... + 00010,,.... + 00000,,.... + -----,,.... + 00101,.... + 00000,.... + -----,.... + 01011.... + 00000.... + -----.... + 10110... + 10011... + -----... + 01010.. + 00000.. + -----.. + 10100. + 10011. + -----. + 01110 + 00000 + ----- + 1110 = Remainder = THE CHECKSUM!!!! + +The division yields a quotient, which we throw away, and a remainder, +which is the calculated checksum. This ends the calculation. + +Usually, the checksum is then appended to the message and the result +transmitted. In this case the transmission would be: 11010110111110. + +At the other end, the receiver can do one of two things: + + a. Separate the message and checksum. Calculate the checksum for + the message (after appending W zeros) and compare the two + checksums. + + b. Checksum the whole lot (without appending zeros) and see if it + comes out as zero! + +These two options are equivalent. However, in the next section, we +will be assuming option b because it is marginally mathematically +cleaner. + +A summary of the operation of the class of CRC algorithms: + + 1. Choose a width W, and a poly G (of width W). + 2. Append W zero bits to the message. Call this M'. + 3. Divide M' by G using CRC arithmetic. The remainder is the checksum. + +That's all there is to it. + +7. Choosing A Poly +------------------ +Choosing a poly is somewhat of a black art and the reader is referred +to [Tanenbaum81] (p.130-132) which has a very clear discussion of this +issue. This section merely aims to put the fear of death into anyone +who so much as toys with the idea of making up their own poly. If you +don't care about why one poly might be better than another and just +want to find out about high-speed implementations, choose one of the +arithmetically sound polys listed at the end of this section and skip +to the next section. + +First note that the transmitted message T is a multiple of the poly. +To see this, note that 1) the last W bits of T is the remainder after +dividing the augmented (by zeros remember) message by the poly, and 2) +addition is the same as subtraction so adding the remainder pushes the +value up to the next multiple. Now note that if the transmitted +message is corrupted in transmission that we will receive T+E where E +is an error vector (and + is CRC addition (i.e. XOR)). Upon receipt of +this message, the receiver divides T+E by G. As T mod G is 0, (T+E) +mod G = E mod G. Thus, the capacity of the poly we choose to catch +particular kinds of errors will be determined by the set of multiples +of G, for any corruption E that is a multiple of G will be undetected. +Our task then is to find classes of G whose multiples look as little +like the kind of line noise (that will be creating the corruptions) as +possible. So let's examine the kinds of line noise we can expect. + +SINGLE BIT ERRORS: A single bit error means E=1000...0000. We can +ensure that this class of error is always detected by making sure that +G has at least two bits set to 1. Any multiple of G will be +constructed using shifting and adding and it is impossible to +construct a value with a single bit by shifting an adding a single +value with more than one bit set, as the two end bits will always +persist. + +TWO-BIT ERRORS: To detect all errors of the form 100...000100...000 +(i.e. E contains two 1 bits) choose a G that does not have multiples +that are 11, 101, 1001, 10001, 100001, etc. It is not clear to me how +one goes about doing this (I don't have the pure maths background), +but Tanenbaum assures us that such G do exist, and cites G with 1 bits +(15,14,1) turned on as an example of one G that won't divide anything +less than 1...1 where ... is 32767 zeros. + +ERRORS WITH AN ODD NUMBER OF BITS: We can catch all corruptions where +E has an odd number of bits by choosing a G that has an even number of +bits. To see this, note that 1) CRC multiplication is simply XORing a +constant value into a register at various offsets, 2) XORing is simply +a bit-flip operation, and 3) if you XOR a value with an even number of +bits into a register, the oddness of the number of 1 bits in the +register remains invariant. Example: Starting with E=111, attempt to +flip all three bits to zero by the repeated application of XORing in +11 at one of the two offsets (i.e. "E=E XOR 011" and "E=E XOR 110") +This is nearly isomorphic to the "glass tumblers" party puzzle where +you challenge someone to flip three tumblers by the repeated +application of the operation of flipping any two. Most of the popular +CRC polys contain an even number of 1 bits. (Note: Tanenbaum states +more specifically that all errors with an odd number of bits can be +caught by making G a multiple of 11). + +BURST ERRORS: A burst error looks like E=000...000111...11110000...00. +That is, E consists of all zeros except for a run of 1s somewhere +inside. This can be recast as E=(10000...00)(1111111...111) where +there are z zeros in the LEFT part and n ones in the RIGHT part. To +catch errors of this kind, we simply set the lowest bit of G to 1. +Doing this ensures that LEFT cannot be a factor of G. Then, so long as +G is wider than RIGHT, the error will be detected. See Tanenbaum for a +clearer explanation of this; I'm a little fuzzy on this one. Note: +Tanenbaum asserts that the probability of a burst of length greater +than W getting through is (0.5)^W. + +That concludes the section on the fine art of selecting polys. + +Some popular polys are: +16 bits: (16,12,5,0) [X25 standard] + (16,15,2,0) ["CRC-16"] +32 bits: (32,26,23,22,16,12,11,10,8,7,5,4,2,1,0) [Ethernet] + + +8. A Straightforward CRC Implementation +--------------------------------------- +That's the end of the theory; now we turn to implementations. To start +with, we examine an absolutely straight-down-the-middle boring +straightforward low-speed implementation that doesn't use any speed +tricks at all. We'll then transform that program progessively until we +end up with the compact table-driven code we all know and love and +which some of us would like to understand. + +To implement a CRC algorithm all we have to do is implement CRC +division. There are two reasons why we cannot simply use the divide +instruction of whatever machine we are on. The first is that we have +to do the divide in CRC arithmetic. The second is that the dividend +might be ten megabytes long, and todays processors do not have +registers that big. + +So to implement CRC division, we have to feed the message through a +division register. At this point, we have to be absolutely precise +about the message data. In all the following examples the message will +be considered to be a stream of bytes (each of 8 bits) with bit 7 of +each byte being considered to be the most significant bit (MSB). The +bit stream formed from these bytes will be the bit stream with the MSB +(bit 7) of the first byte first, going down to bit 0 of the first +byte, and then the MSB of the second byte and so on. + +With this in mind, we can sketch an implementation of the CRC +division. For the purposes of example, consider a poly with W=4 and +the poly=10111. Then, the perform the division, we need to use a 4-bit +register: + + 3 2 1 0 Bits + +---+---+---+---+ + Pop! <-- | | | | | <----- Augmented message + +---+---+---+---+ + + 1 0 1 1 1 = The Poly + +(Reminder: The augmented message is the message followed by W zero bits.) + +To perform the division perform the following: + + Load the register with zero bits. + Augment the message by appending W zero bits to the end of it. + While (more message bits) + Begin + Shift the register left by one bit, reading the next bit of the + augmented message into register bit position 0. + If (a 1 bit popped out of the register during step 3) + Register = Register XOR Poly. + End + The register now contains the remainder. + +(Note: In practice, the IF condition can be tested by testing the top + bit of R before performing the shift.) + +We will call this algorithm "SIMPLE". + +This might look a bit messy, but all we are really doing is +"subtracting" various powers (i.e. shiftings) of the poly from the +message until there is nothing left but the remainder. Study the +manual examples of long division if you don't understand this. + +It should be clear that the above algorithm will work for any width W. + + +9. A Table-Driven Implementation +-------------------------------- +The SIMPLE algorithm above is a good starting point because it +corresponds directly to the theory presented so far, and because it is +so SIMPLE. However, because it operates at the bit level, it is rather +awkward to code (even in C), and inefficient to execute (it has to +loop once for each bit). To speed it up, we need to find a way to +enable the algorithm to process the message in units larger than one +bit. Candidate quantities are nibbles (4 bits), bytes (8 bits), words +(16 bits) and longwords (32 bits) and higher if we can achieve it. Of +these, 4 bits is best avoided because it does not correspond to a byte +boundary. At the very least, any speedup should allow us to operate at +byte boundaries, and in fact most of the table driven algorithms +operate a byte at a time. + +For the purposes of discussion, let us switch from a 4-bit poly to a +32-bit one. Our register looks much the same, except the boxes +represent bytes instead of bits, and the Poly is 33 bits (one implicit +1 bit at the top and 32 "active" bits) (W=32). + + 3 2 1 0 Bytes + +----+----+----+----+ + Pop! <-- | | | | | <----- Augmented message + +----+----+----+----+ + + 1<------32 bits------> + +The SIMPLE algorithm is still applicable. Let us examine what it does. +Imagine that the SIMPLE algorithm is in full swing and consider the +top 8 bits of the 32-bit register (byte 3) to have the values: + + t7 t6 t5 t4 t3 t2 t1 t0 + +In the next iteration of SIMPLE, t7 will determine whether the Poly +will be XORed into the entire register. If t7=1, this will happen, +otherwise it will not. Suppose that the top 8 bits of the poly are g7 +g6.. g0, then after the next iteration, the top byte will be: + + t6 t5 t4 t3 t2 t1 t0 ?? ++ t7 * (g7 g6 g5 g4 g3 g2 g1 g0) [Reminder: + is XOR] + +The NEW top bit (that will control what happens in the next iteration) +now has the value t6 + t7*g7. The important thing to notice here is +that from an informational point of view, all the information required +to calculate the NEW top bit was present in the top TWO bits of the +original top byte. Similarly, the NEXT top bit can be calculated in +advance SOLELY from the top THREE bits t7, t6, and t5. In fact, in +general, the value of the top bit in the register in k iterations can +be calculated from the top k bits of the register. Let us take this +for granted for a moment. + +Consider for a moment that we use the top 8 bits of the register to +calculate the value of the top bit of the register during the next 8 +iterations. Suppose that we drive the next 8 iterations using the +calculated values (which we could perhaps store in a single byte +register and shift out to pick off each bit). Then we note three +things: + + * The top byte of the register now doesn't matter. No matter how + many times and at what offset the poly is XORed to the top 8 + bits, they will all be shifted out the right hand side during the + next 8 iterations anyway. + + + * The remaining bits will be shifted left one position and the + rightmost byte of the register will be shifted in the next byte + + AND + + * While all this is going on, the register will be subjected to a + series of XOR's in accordance with the bits of the pre-calculated + control byte. + +Now consider the effect of XORing in a constant value at various +offsets to a register. For example: + + 0100010 Register + ...0110 XOR this + ..0110. XOR this + 0110... XOR this + ------- + 0011000 + ------- + +The point of this is that you can XOR constant values into a register +to your heart's delight, and in the end, there will exist a value +which when XORed in with the original register will have the same +effect as all the other XORs. + +Perhaps you can see the solution now. Putting all the pieces together +we have an algorithm that goes like this: + + While (augmented message is not exhausted) + Begin + Examine the top byte of the register + Calculate the control byte from the top byte of the register + Sum all the Polys at various offsets that are to be XORed into + the register in accordance with the control byte + Shift the register left by one byte, reading a new message byte + into the rightmost byte of the register + XOR the summed polys to the register + End + +As it stands this is not much better than the SIMPLE algorithm. +However, it turns out that most of the calculation can be precomputed +and assembled into a table. As a result, the above algorithm can be +reduced to: + + While (augmented message is not exhaused) + Begin + Top = top_byte(Register); + Register = (Register << 24) | next_augmessage_byte; + Register = Register XOR precomputed_table[Top]; + End + +There! If you understand this, you've grasped the main idea of +table-driven CRC algorithms. The above is a very efficient algorithm +requiring just a shift, and OR, an XOR, and a table lookup per byte. +Graphically, it looks like this: + + 3 2 1 0 Bytes + +----+----+----+----+ + +-----<| | | | | <----- Augmented message + | +----+----+----+----+ + | ^ + | | + | XOR + | | + | 0+----+----+----+----+ Algorithm + v +----+----+----+----+ --------- + | +----+----+----+----+ 1. Shift the register left by + | +----+----+----+----+ one byte, reading in a new + | +----+----+----+----+ message byte. + | +----+----+----+----+ 2. Use the top byte just rotated + | +----+----+----+----+ out of the register to index + +----->+----+----+----+----+ the table of 256 32-bit values. + +----+----+----+----+ 3. XOR the table value into the + +----+----+----+----+ register. + +----+----+----+----+ 4. Goto 1 iff more augmented + +----+----+----+----+ message bytes. + 255+----+----+----+----+ + + +In C, the algorithm main loop looks like this: + + r=0; + while (len--) + { + byte t = (r >> 24) & 0xFF; + r = (r << 8) | *p++; + r^=table[t]; + } + +where len is the length of the augmented message in bytes, p points to +the augmented message, r is the register, t is a temporary, and table +is the computed table. This code can be made even more unreadable as +follows: + + r=0; while (len--) r = ((r << 8) | *p++) ^ t[(r >> 24) & 0xFF]; + +This is a very clean, efficient loop, although not a very obvious one +to the casual observer not versed in CRC theory. We will call this the +TABLE algorithm. + + +10. A Slightly Mangled Table-Driven Implementation +-------------------------------------------------- +Despite the terse beauty of the line + + r=0; while (len--) r = ((r << 8) | *p++) ^ t[(r >> 24) & 0xFF]; + +those optimizing hackers couldn't leave it alone. The trouble, you +see, is that this loop operates upon the AUGMENTED message and in +order to use this code, you have to append W/8 zero bytes to the end +of the message before pointing p at it. Depending on the run-time +environment, this may or may not be a problem; if the block of data +was handed to us by some other code, it could be a BIG problem. One +alternative is simply to append the following line after the above +loop, once for each zero byte: + + for (i=0; i> 24) & 0xFF]; + +This looks like a sane enough solution to me. However, at the further +expense of clarity (which, you must admit, is already a pretty scare +commodity in this code) we can reorganize this small loop further so +as to avoid the need to either augment the message with zero bytes, or +to explicitly process zero bytes at the end as above. To explain the +optimization, we return to the processing diagram given earlier. + + 3 2 1 0 Bytes + +----+----+----+----+ + +-----<| | | | | <----- Augmented message + | +----+----+----+----+ + | ^ + | | + | XOR + | | + | 0+----+----+----+----+ Algorithm + v +----+----+----+----+ --------- + | +----+----+----+----+ 1. Shift the register left by + | +----+----+----+----+ one byte, reading in a new + | +----+----+----+----+ message byte. + | +----+----+----+----+ 2. Use the top byte just rotated + | +----+----+----+----+ out of the register to index + +----->+----+----+----+----+ the table of 256 32-bit values. + +----+----+----+----+ 3. XOR the table value into the + +----+----+----+----+ register. + +----+----+----+----+ 4. Goto 1 iff more augmented + +----+----+----+----+ message bytes. + 255+----+----+----+----+ + +Now, note the following facts: + +TAIL: The W/4 augmented zero bytes that appear at the end of the + message will be pushed into the register from the right as all + the other bytes are, but their values (0) will have no effect + whatsoever on the register because 1) XORing with zero does not + change the target byte, and 2) the four bytes are never + propagated out the left side of the register where their + zeroness might have some sort of influence. Thus, the sole + function of the W/4 augmented zero bytes is to drive the + calculation for another W/4 byte cycles so that the end of the + REAL data passes all the way through the register. + +HEAD: If the initial value of the register is zero, the first four + iterations of the loop will have the sole effect of shifting in + the first four bytes of the message from the right. This is + because the first 32 control bits are all zero and so nothing is + XORed into the register. Even if the initial value is not zero, + the first 4 byte iterations of the algorithm will have the sole + effect of shifting the first 4 bytes of the message into the + register and then XORing them with some constant value (that is + a function of the initial value of the register). + +These facts, combined with the XOR property + + (A xor B) xor C = A xor (B xor C) + +mean that message bytes need not actually travel through the W/4 bytes +of the register. Instead, they can be XORed into the top byte just +before it is used to index the lookup table. This leads to the +following modified version of the algorithm. + + + +-----+----+----+----+----+ next message byte to yield an + +----+----+----+----+ index into the table ([0,255]). + +----+----+----+----+ 3. XOR the table value into the + +----+----+----+----+ register. + +----+----+----+----+ 4. Goto 1 iff more augmented + 255+----+----+----+----+ message bytes. + + +Note: The initial register value for this algorithm must be the +initial value of the register for the previous algorithm fed through +the table four times. Note: The table is such that if the previous +algorithm used 0, the new algorithm will too. + +This is an IDENTICAL algorithm and will yield IDENTICAL results. The C +code looks something like this: + + r=0; while (len--) r = (r<<8) ^ t[(r >> 24) ^ *p++]; + +and THIS is the code that you are likely to find inside current +table-driven CRC implementations. Some FF masks might have to be ANDed +in here and there for portability's sake, but basically, the above +loop is IT. We will call this the DIRECT TABLE ALGORITHM. + +During the process of trying to understand all this stuff, I managed +to derive the SIMPLE algorithm and the table-driven version derived +from that. However, when I compared my code with the code found in +real-implementations, I was totally bamboozled as to why the bytes +were being XORed in at the wrong end of the register! It took quite a +while before I figured out that theirs and my algorithms were actually +the same. Part of why I am writing this document is that, while the +link between division and my earlier table-driven code is vaguely +apparent, any such link is fairly well erased when you start pumping +bytes in at the "wrong end" of the register. It looks all wrong! + +If you've got this far, you not only understand the theory, the +practice, the optimized practice, but you also understand the real +code you are likely to run into. Could get any more complicated? Yes +it can. + + +11. "Reflected" Table-Driven Implementations +-------------------------------------------- +Despite the fact that the above code is probably optimized about as +much as it could be, this did not stop some enterprising individuals +from making things even more complicated. To understand how this +happened, we have to enter the world of hardware. + +DEFINITION: A value/register is reflected if it's bits are swapped +around its centre. For example: 0101 is the 4-bit reflection of 1010. +0011 is the reflection of 1100. +0111-0101-1010-1111-0010-0101-1011-1100 is the reflection of +0011-1101-1010-0100-1111-0101-1010-1110. + +Turns out that UARTs (those handy little chips that perform serial IO) +are in the habit of transmitting each byte with the least significant +bit (bit 0) first and the most significant bit (bit 7) last (i.e. +reflected). An effect of this convention is that hardware engineers +constructing hardware CRC calculators that operate at the bit level +took to calculating CRCs of bytes streams with each of the bytes +reflected within itself. The bytes are processed in the same order, +but the bits in each byte are swapped; bit 0 is now bit 7, bit 1 is +now bit 6, and so on. Now this wouldn't matter much if this convention +was restricted to hardware land. However it seems that at some stage +some of these CRC values were presented at the software level and +someone had to write some code that would interoperate with the +hardware CRC calculation. + +In this situation, a normal sane software engineer would simply +reflect each byte before processing it. However, it would seem that +normal sane software engineers were thin on the ground when this early +ground was being broken, because instead of reflecting the bytes, +whoever was responsible held down the byte and reflected the world, +leading to the following "reflected" algorithm which is identical to +the previous one except that everything is reflected except the input +bytes. + + + Message (non augmented) >-----+ + | + Bytes 0 1 2 3 v + +----+----+----+----+ | + | | | | |>----XOR + +----+----+----+----+ | + ^ | + | | + XOR | + | | + +----+----+----+----+0 | + +----+----+----+----+ v + +----+----+----+----+ | + +----+----+----+----+ | + +----+----+----+----+ | + +----+----+----+----+ | + +----+----+----+----+ | + +----+----+----+----+<-----+ + +----+----+----+----+ + +----+----+----+----+ + +----+----+----+----+ + +----+----+----+----+ + +----+----+----+----+255 + +Notes: + + * The table is identical to the one in the previous algorithm + except that each entry has been reflected. + + * The initial value of the register is the same as in the previous + algorithm except that it has been reflected. + + * The bytes of the message are processed in the same order as + before (i.e. the message itself is not reflected). + + * The message bytes themselves don't need to be explicitly + reflected, because everything else has been! + +At the end of execution, the register contains the reflection of the +final CRC value (remainder). Actually, I'm being rather hard on +whoever cooked this up because it seems that hardware implementations +of the CRC algorithm used the reflected checksum value and so +producing a reflected CRC was just right. In fact reflecting the world +was probably a good engineering solution - if a confusing one. + +We will call this the REFLECTED algorithm. + +Whether or not it made sense at the time, the effect of having +reflected algorithms kicking around the world's FTP sites is that +about half the CRC implementations one runs into are reflected and the +other half not. It's really terribly confusing. In particular, it +would seem to me that the casual reader who runs into a reflected, +table-driven implementation with the bytes "fed in the wrong end" +would have Buckley's chance of ever connecting the code to the concept +of binary mod 2 division. + +It couldn't get any more confusing could it? Yes it could. + + +12. "Reversed" Polys +-------------------- +As if reflected implementations weren't enough, there is another +concept kicking around which makes the situation bizaarly confusing. +The concept is reversed Polys. + +It turns out that the reflection of good polys tend to be good polys +too! That is, if G=11101 is a good poly value, then 10111 will be as +well. As a consequence, it seems that every time an organization (such +as CCITT) standardizes on a particularly good poly ("polynomial"), +those in the real world can't leave the poly's reflection alone +either. They just HAVE to use it. As a result, the set of "standard" +poly's has a corresponding set of reflections, which are also in use. +To avoid confusion, we will call these the "reversed" polys. + + X25 standard: 1-0001-0000-0010-0001 + X25 reversed: 1-0000-1000-0001-0001 + + CRC16 standard: 1-1000-0000-0000-0101 + CRC16 reversed: 1-0100-0000-0000-0011 + +Note that here it is the entire poly that is being reflected/reversed, +not just the bottom W bits. This is an important distinction. In the +reflected algorithm described in the previous section, the poly used +in the reflected algorithm was actually identical to that used in the +non-reflected algorithm; all that had happened is that the bytes had +effectively been reflected. As such, all the 16-bit/32-bit numbers in +the algorithm had to be reflected. In contrast, the ENTIRE poly +includes the implicit one bit at the top, and so reversing a poly is +not the same as reflecting its bottom 16 or 32 bits. + +The upshot of all this is that a reflected algorithm is not equivalent +to the original algorithm with the poly reflected. Actually, this is +probably less confusing than if they were duals. + +If all this seems a bit unclear, don't worry, because we're going to +sort it all out "real soon now". Just one more section to go before +that. + + +13. Initial and Final Values +---------------------------- +In addition to the complexity already seen, CRC algorithms differ from +each other in two other regards: + + * The initial value of the register. + + * The value to be XORed with the final register value. + +For example, the "CRC32" algorithm initializes its register to +FFFFFFFF and XORs the final register value with FFFFFFFF. + +Most CRC algorithms initialize their register to zero. However, some +initialize it to a non-zero value. In theory (i.e. with no assumptions +about the message), the initial value has no affect on the strength of +the CRC algorithm, the initial value merely providing a fixed starting +point from which the register value can progress. However, in +practice, some messages are more likely than others, and it is wise to +initialize the CRC algorithm register to a value that does not have +"blind spots" that are likely to occur in practice. By "blind spot" is +meant a sequence of message bytes that do not result in the register +changing its value. In particular, any CRC algorithm that initializes +its register to zero will have a blind spot of zero when it starts up +and will be unable to "count" a leading run of zero bytes. As a +leading run of zero bytes is quite common in real messages, it is wise +to initialize the algorithm register to a non-zero value. + + +14. Defining Algorithms Absolutely +---------------------------------- +At this point we have covered all the different aspects of +table-driven CRC algorithms. As there are so many variations on these +algorithms, it is worth trying to establish a nomenclature for them. +This section attempts to do that. + +We have seen that CRC algorithms vary in: + + * Width of the poly (polynomial). + * Value of the poly. + * Initial value for the register. + * Whether the bits of each byte are reflected before being processed. + * Whether the algorithm feeds input bytes through the register or + xors them with a byte from one end and then straight into the table. + * Whether the final register value should be reversed (as in reflected + versions). + * Value to XOR with the final register value. + +In order to be able to talk about particular CRC algorithms, we need +to able to define them more precisely than this. For this reason, the +next section attempts to provide a well-defined parameterized model +for CRC algorithms. To refer to a particular algorithm, we need then +simply specify the algorithm in terms of parameters to the model. + + +15. A Parameterized Model For CRC Algorithms +-------------------------------------------- +In this section we define a precise parameterized model CRC algorithm +which, for want of a better name, we will call the "Rocksoft^tm Model +CRC Algorithm" (and why not? Rocksoft^tm could do with some free +advertising :-). + +The most important aspect of the model algorithm is that it focusses +exclusively on functionality, ignoring all implementation details. The +aim of the exercise is to construct a way of referring precisely to +particular CRC algorithms, regardless of how confusingly they are +implemented. To this end, the model must be as simple and precise as +possible, with as little confusion as possible. + +The Rocksoft^tm Model CRC Algorithm is based essentially on the DIRECT +TABLE ALGORITHM specified earlier. However, the algorithm has to be +further parameterized to enable it to behave in the same way as some +of the messier algorithms out in the real world. + +To enable the algorithm to behave like reflected algorithms, we +provide a boolean option to reflect the input bytes, and a boolean +option to specify whether to reflect the output checksum value. By +framing reflection as an input/output transformation, we avoid the +confusion of having to mentally map the parameters of reflected and +non-reflected algorithms. + +An extra parameter allows the algorithm's register to be initialized +to a particular value. A further parameter is XORed with the final +value before it is returned. + +By putting all these pieces together we end up with the parameters of +the algorithm: + + NAME: This is a name given to the algorithm. A string value. + + WIDTH: This is the width of the algorithm expressed in bits. This + is one less than the width of the Poly. + + POLY: This parameter is the poly. This is a binary value that + should be specified as a hexadecimal number. The top bit of the + poly should be omitted. For example, if the poly is 10110, you + should specify 06. An important aspect of this parameter is that it + represents the unreflected poly; the bottom bit of this parameter + is always the LSB of the divisor during the division regardless of + whether the algorithm being modelled is reflected. + + INIT: This parameter specifies the initial value of the register + when the algorithm starts. This is the value that is to be assigned + to the register in the direct table algorithm. In the table + algorithm, we may think of the register always commencing with the + value zero, and this value being XORed into the register after the + N'th bit iteration. This parameter should be specified as a + hexadecimal number. + + REFIN: This is a boolean parameter. If it is FALSE, input bytes are + processed with bit 7 being treated as the most significant bit + (MSB) and bit 0 being treated as the least significant bit. If this + parameter is FALSE, each byte is reflected before being processed. + + REFOUT: This is a boolean parameter. If it is set to FALSE, the + final value in the register is fed into the XOROUT stage directly, + otherwise, if this parameter is TRUE, the final register value is + reflected first. + + XOROUT: This is an W-bit value that should be specified as a + hexadecimal number. It is XORed to the final register value (after + the REFOUT) stage before the value is returned as the official + checksum. + + CHECK: This field is not strictly part of the definition, and, in + the event of an inconsistency between this field and the other + field, the other fields take precedence. This field is a check + value that can be used as a weak validator of implementations of + the algorithm. The field contains the checksum obtained when the + ASCII string "123456789" is fed through the specified algorithm + (i.e. 313233... (hexadecimal)). + +With these parameters defined, the model can now be used to specify a +particular CRC algorithm exactly. Here is an example specification for +a popular form of the CRC-16 algorithm. + + Name : "CRC-16" + Width : 16 + Poly : 8005 + Init : 0000 + RefIn : True + RefOut : True + XorOut : 0000 + Check : BB3D + + +16. A Catalog of Parameter Sets for Standards +--------------------------------------------- +At this point, I would like to give a list of the specifications for +commonly used CRC algorithms. However, most of the algorithms that I +have come into contact with so far are specified in such a vague way +that this has not been possible. What I can provide is a list of polys +for various CRC standards I have heard of: + + X25 standard : 1021 [CRC-CCITT, ADCCP, SDLC/HDLC] + X25 reversed : 0811 + + CRC16 standard : 8005 + CRC16 reversed : 4003 [LHA] + + CRC32 : 04C11DB7 [PKZIP, AUTODIN II, Ethernet, FDDI] + +I would be interested in hearing from anyone out there who can tie +down the complete set of model parameters for any of these standards. + +However, a program that was kicking around seemed to imply the +following specifications. Can anyone confirm or deny them (or provide +the check values (which I couldn't be bothered coding up and +calculating)). + + Name : "CRC-16/CITT" + Width : 16 + Poly : 1021 + Init : FFFF + RefIn : False + RefOut : False + XorOut : 0000 + Check : ? + + + Name : "XMODEM" + Width : 16 + Poly : 8408 + Init : 0000 + RefIn : True + RefOut : True + XorOut : 0000 + Check : ? + + + Name : "ARC" + Width : 16 + Poly : 8005 + Init : 0000 + RefIn : True + RefOut : True + XorOut : 0000 + Check : ? + +Here is the specification for the CRC-32 algorithm which is reportedly +used in PKZip, AUTODIN II, Ethernet, and FDDI. + + Name : "CRC-32" + Width : 32 + Poly : 04C11DB7 + Init : FFFFFFFF + RefIn : True + RefOut : True + XorOut : FFFFFFFF + Check : CBF43926 + + +17. An Implementation of the Model Algorithm +-------------------------------------------- +Here is an implementation of the model algorithm in the C programming +language. The implementation consists of a header file (.h) and an +implementation file (.c). If you're reading this document in a +sequential scroller, you can skip this code by searching for the +string "Roll Your Own". + +To ensure that the following code is working, configure it for the +CRC-16 and CRC-32 algorithms given above and ensure that they produce +the specified "check" checksum when fed the test string "123456789" +(see earlier). + +/******************************************************************************/ +/* Start of crcmodel.h */ +/******************************************************************************/ +/* */ +/* Author : Ross Williams (ross@guest.adelaide.edu.au.). */ +/* Date : 3 June 1993. */ +/* Status : Public domain. */ +/* */ +/* Description : This is the header (.h) file for the reference */ +/* implementation of the Rocksoft^tm Model CRC Algorithm. For more */ +/* information on the Rocksoft^tm Model CRC Algorithm, see the document */ +/* titled "A Painless Guide to CRC Error Detection Algorithms" by Ross */ +/* Williams (ross@guest.adelaide.edu.au.). This document is likely to be in */ +/* "ftp.adelaide.edu.au/pub/rocksoft". */ +/* */ +/* Note: Rocksoft is a trademark of Rocksoft Pty Ltd, Adelaide, Australia. */ +/* */ +/******************************************************************************/ +/* */ +/* How to Use This Package */ +/* ----------------------- */ +/* Step 1: Declare a variable of type cm_t. Declare another variable */ +/* (p_cm say) of type p_cm_t and initialize it to point to the first */ +/* variable (e.g. p_cm_t p_cm = &cm_t). */ +/* */ +/* Step 2: Assign values to the parameter fields of the structure. */ +/* If you don't know what to assign, see the document cited earlier. */ +/* For example: */ +/* p_cm->cm_width = 16; */ +/* p_cm->cm_poly = 0x8005L; */ +/* p_cm->cm_init = 0L; */ +/* p_cm->cm_refin = TRUE; */ +/* p_cm->cm_refot = TRUE; */ +/* p_cm->cm_xorot = 0L; */ +/* Note: Poly is specified without its top bit (18005 becomes 8005). */ +/* Note: Width is one bit less than the raw poly width. */ +/* */ +/* Step 3: Initialize the instance with a call cm_ini(p_cm); */ +/* */ +/* Step 4: Process zero or more message bytes by placing zero or more */ +/* successive calls to cm_nxt. Example: cm_nxt(p_cm,ch); */ +/* */ +/* Step 5: Extract the CRC value at any time by calling crc = cm_crc(p_cm); */ +/* If the CRC is a 16-bit value, it will be in the bottom 16 bits. */ +/* */ +/******************************************************************************/ +/* */ +/* Design Notes */ +/* ------------ */ +/* PORTABILITY: This package has been coded very conservatively so that */ +/* it will run on as many machines as possible. For example, all external */ +/* identifiers have been restricted to 6 characters and all internal ones to */ +/* 8 characters. The prefix cm (for Crc Model) is used as an attempt to avoid */ +/* namespace collisions. This package is endian independent. */ +/* */ +/* EFFICIENCY: This package (and its interface) is not designed for */ +/* speed. The purpose of this package is to act as a well-defined reference */ +/* model for the specification of CRC algorithms. If you want speed, cook up */ +/* a specific table-driven implementation as described in the document cited */ +/* above. This package is designed for validation only; if you have found or */ +/* implemented a CRC algorithm and wish to describe it as a set of parameters */ +/* to the Rocksoft^tm Model CRC Algorithm, your CRC algorithm implementation */ +/* should behave identically to this package under those parameters. */ +/* */ +/******************************************************************************/ + +/* The following #ifndef encloses this entire */ +/* header file, rendering it indempotent. */ +#ifndef CM_DONE +#define CM_DONE + +/******************************************************************************/ + +/* The following definitions are extracted from my style header file which */ +/* would be cumbersome to distribute with this package. The DONE_STYLE is the */ +/* idempotence symbol used in my style header file. */ + +#ifndef DONE_STYLE + +typedef unsigned long ulong; +typedef unsigned bool; +typedef unsigned char * p_ubyte_; + +#ifndef TRUE +#define FALSE 0 +#define TRUE 1 +#endif + +/* Change to the second definition if you don't have prototypes. */ +#define P_(A) A +/* #define P_(A) () */ + +/* Uncomment this definition if you don't have void. */ +/* typedef int void; */ + +#endif + +/******************************************************************************/ + +/* CRC Model Abstract Type */ +/* ----------------------- */ +/* The following type stores the context of an executing instance of the */ +/* model algorithm. Most of the fields are model parameters which must be */ +/* set before the first initializing call to cm_ini. */ +typedef struct + { + int cm_width; /* Parameter: Width in bits [8,32]. */ + ulong cm_poly; /* Parameter: The algorithm's polynomial. */ + ulong cm_init; /* Parameter: Initial register value. */ + bool cm_refin; /* Parameter: Reflect input bytes? */ + bool cm_refot; /* Parameter: Reflect output CRC? */ + ulong cm_xorot; /* Parameter: XOR this to output CRC. */ + + ulong cm_reg; /* Context: Context during execution. */ + } cm_t; +typedef cm_t *p_cm_t; + +/******************************************************************************/ + +/* Functions That Implement The Model */ +/* ---------------------------------- */ +/* The following functions animate the cm_t abstraction. */ + +void cm_ini P_((p_cm_t p_cm)); +/* Initializes the argument CRC model instance. */ +/* All parameter fields must be set before calling this. */ + +void cm_nxt P_((p_cm_t p_cm,int ch)); +/* Processes a single message byte [0,255]. */ + +void cm_blk P_((p_cm_t p_cm,p_ubyte_ blk_adr,ulong blk_len)); +/* Processes a block of message bytes. */ + +ulong cm_crc P_((p_cm_t p_cm)); +/* Returns the CRC value for the message bytes processed so far. */ + +/******************************************************************************/ + +/* Functions For Table Calculation */ +/* ------------------------------- */ +/* The following function can be used to calculate a CRC lookup table. */ +/* It can also be used at run-time to create or check static tables. */ + +ulong cm_tab P_((p_cm_t p_cm,int index)); +/* Returns the i'th entry for the lookup table for the specified algorithm. */ +/* The function examines the fields cm_width, cm_poly, cm_refin, and the */ +/* argument table index in the range [0,255] and returns the table entry in */ +/* the bottom cm_width bytes of the return value. */ + +/******************************************************************************/ + +/* End of the header file idempotence #ifndef */ +#endif + +/******************************************************************************/ +/* End of crcmodel.h */ +/******************************************************************************/ + + +/******************************************************************************/ +/* Start of crcmodel.c */ +/******************************************************************************/ +/* */ +/* Author : Ross Williams (ross@guest.adelaide.edu.au.). */ +/* Date : 3 June 1993. */ +/* Status : Public domain. */ +/* */ +/* Description : This is the implementation (.c) file for the reference */ +/* implementation of the Rocksoft^tm Model CRC Algorithm. For more */ +/* information on the Rocksoft^tm Model CRC Algorithm, see the document */ +/* titled "A Painless Guide to CRC Error Detection Algorithms" by Ross */ +/* Williams (ross@guest.adelaide.edu.au.). This document is likely to be in */ +/* "ftp.adelaide.edu.au/pub/rocksoft". */ +/* */ +/* Note: Rocksoft is a trademark of Rocksoft Pty Ltd, Adelaide, Australia. */ +/* */ +/******************************************************************************/ +/* */ +/* Implementation Notes */ +/* -------------------- */ +/* To avoid inconsistencies, the specification of each function is not echoed */ +/* here. See the header file for a description of these functions. */ +/* This package is light on checking because I want to keep it short and */ +/* simple and portable (i.e. it would be too messy to distribute my entire */ +/* C culture (e.g. assertions package) with this package. */ +/* */ +/******************************************************************************/ + +#include "crcmodel.h" + +/******************************************************************************/ + +/* The following definitions make the code more readable. */ + +#define BITMASK(X) (1L << (X)) +#define MASK32 0xFFFFFFFFL +#define LOCAL static + +/******************************************************************************/ + +LOCAL ulong reflect P_((ulong v,int b)); +LOCAL ulong reflect (v,b) +/* Returns the value v with the bottom b [0,32] bits reflected. */ +/* Example: reflect(0x3e23L,3) == 0x3e26 */ +ulong v; +int b; +{ + int i; + ulong t = v; + for (i=0; i>=1; + } + return v; +} + +/******************************************************************************/ + +LOCAL ulong widmask P_((p_cm_t)); +LOCAL ulong widmask (p_cm) +/* Returns a longword whose value is (2^p_cm->cm_width)-1. */ +/* The trick is to do this portably (e.g. without doing <<32). */ +p_cm_t p_cm; +{ + return (((1L<<(p_cm->cm_width-1))-1L)<<1)|1L; +} + +/******************************************************************************/ + +void cm_ini (p_cm) +p_cm_t p_cm; +{ + p_cm->cm_reg = p_cm->cm_init; +} + +/******************************************************************************/ + +void cm_nxt (p_cm,ch) +p_cm_t p_cm; +int ch; +{ + int i; + ulong uch = (ulong) ch; + ulong topbit = BITMASK(p_cm->cm_width-1); + + if (p_cm->cm_refin) uch = reflect(uch,8); + p_cm->cm_reg ^= (uch << (p_cm->cm_width-8)); + for (i=0; i<8; i++) + { + if (p_cm->cm_reg & topbit) + p_cm->cm_reg = (p_cm->cm_reg << 1) ^ p_cm->cm_poly; + else + p_cm->cm_reg <<= 1; + p_cm->cm_reg &= widmask(p_cm); + } +} + +/******************************************************************************/ + +void cm_blk (p_cm,blk_adr,blk_len) +p_cm_t p_cm; +p_ubyte_ blk_adr; +ulong blk_len; +{ + while (blk_len--) cm_nxt(p_cm,*blk_adr++); +} + +/******************************************************************************/ + +ulong cm_crc (p_cm) +p_cm_t p_cm; +{ + if (p_cm->cm_refot) + return p_cm->cm_xorot ^ reflect(p_cm->cm_reg,p_cm->cm_width); + else + return p_cm->cm_xorot ^ p_cm->cm_reg; +} + +/******************************************************************************/ + +ulong cm_tab (p_cm,index) +p_cm_t p_cm; +int index; +{ + int i; + ulong r; + ulong topbit = BITMASK(p_cm->cm_width-1); + ulong inbyte = (ulong) index; + + if (p_cm->cm_refin) inbyte = reflect(inbyte,8); + r = inbyte << (p_cm->cm_width-8); + for (i=0; i<8; i++) + if (r & topbit) + r = (r << 1) ^ p_cm->cm_poly; + else + r<<=1; + if (p_cm->cm_refin) r = reflect(r,p_cm->cm_width); + return r & widmask(p_cm); +} + +/******************************************************************************/ +/* End of crcmodel.c */ +/******************************************************************************/ + + +18. Roll Your Own Table-Driven Implementation +--------------------------------------------- +Despite all the fuss I've made about understanding and defining CRC +algorithms, the mechanics of their high-speed implementation remains +trivial. There are really only two forms: normal and reflected. Normal +shifts to the left and covers the case of algorithms with Refin=FALSE +and Refot=FALSE. Reflected shifts to the right and covers algorithms +with both those parameters true. (If you want one parameter true and +the other false, you'll have to figure it out for yourself!) The +polynomial is embedded in the lookup table (to be discussed). The +other parameters, Init and XorOt can be coded as macros. Here is the +32-bit normal form (the 16-bit form is similar). + + unsigned long crc_normal (); + unsigned long crc_normal (blk_adr,blk_len) + unsigned char *blk_adr; + unsigned long blk_len; + { + unsigned long crc = INIT; + while (blk_len--) + crc = crctable[((crc>>24) ^ *blk_adr++) & 0xFFL] ^ (crc << 8); + return crc ^ XOROT; + } + +Here is the reflected form: + + unsigned long crc_reflected (); + unsigned long crc_reflected (blk_adr,blk_len) + unsigned char *blk_adr; + unsigned long blk_len; + { + unsigned long crc = INIT_REFLECTED; + while (blk_len--) + crc = crctable[(crc ^ *blk_adr++) & 0xFFL] ^ (crc >> 8)); + return crc ^ XOROT; + } + +Note: I have carefully checked the above two code fragments, but I +haven't actually compiled or tested them. This shouldn't matter to +you, as, no matter WHAT you code, you will always be able to tell if +you have got it right by running whatever you have created against the +reference model given earlier. The code fragments above are really +just a rough guide. The reference model is the definitive guide. + +Note: If you don't care much about speed, just use the reference model +code! + + +19. Generating A Lookup Table +----------------------------- +The only component missing from the normal and reversed code fragments +in the previous section is the lookup table. The lookup table can be +computed at run time using the cm_tab function of the model package +given earlier, or can be pre-computed and inserted into the C program. +In either case, it should be noted that the lookup table depends only +on the POLY and RefIn (and RefOt) parameters. Basically, the +polynomial determines the table, but you can generate a reflected +table too if you want to use the reflected form above. + +The following program generates any desired 16-bit or 32-bit lookup +table. Skip to the word "Summary" if you want to skip over this code. + + + +/******************************************************************************/ +/* Start of crctable.c */ +/******************************************************************************/ +/* */ +/* Author : Ross Williams (ross@guest.adelaide.edu.au.). */ +/* Date : 3 June 1993. */ +/* Version : 1.0. */ +/* Status : Public domain. */ +/* */ +/* Description : This program writes a CRC lookup table (suitable for */ +/* inclusion in a C program) to a designated output file. The program can be */ +/* statically configured to produce any table covered by the Rocksoft^tm */ +/* Model CRC Algorithm. For more information on the Rocksoft^tm Model CRC */ +/* Algorithm, see the document titled "A Painless Guide to CRC Error */ +/* Detection Algorithms" by Ross Williams (ross@guest.adelaide.edu.au.). This */ +/* document is likely to be in "ftp.adelaide.edu.au/pub/rocksoft". */ +/* */ +/* Note: Rocksoft is a trademark of Rocksoft Pty Ltd, Adelaide, Australia. */ +/* */ +/******************************************************************************/ + +#include +#include +#include "crcmodel.h" + +/******************************************************************************/ + +/* TABLE PARAMETERS */ +/* ================ */ +/* The following parameters entirely determine the table to be generated. You */ +/* should need to modify only the definitions in this section before running */ +/* this program. */ +/* */ +/* TB_FILE is the name of the output file. */ +/* TB_WIDTH is the table width in bytes (either 2 or 4). */ +/* TB_POLY is the "polynomial", which must be TB_WIDTH bytes wide. */ +/* TB_REVER indicates whether the table is to be reversed (reflected). */ +/* */ +/* Example: */ +/* */ +/* #define TB_FILE "crctable.out" */ +/* #define TB_WIDTH 2 */ +/* #define TB_POLY 0x8005L */ +/* #define TB_REVER TRUE */ + +#define TB_FILE "crctable.out" +#define TB_WIDTH 4 +#define TB_POLY 0x04C11DB7L +#define TB_REVER TRUE + +/******************************************************************************/ + +/* Miscellaneous definitions. */ + +#define LOCAL static +FILE *outfile; +#define WR(X) fprintf(outfile,(X)) +#define WP(X,Y) fprintf(outfile,(X),(Y)) + +/******************************************************************************/ + +LOCAL void chk_err P_((char *)); +LOCAL void chk_err (mess) +/* If mess is non-empty, write it out and abort. Otherwise, check the error */ +/* status of outfile and abort if an error has occurred. */ +char *mess; +{ + if (mess[0] != 0 ) {printf("%s\n",mess); exit(EXIT_FAILURE);} + if (ferror(outfile)) {perror("chk_err"); exit(EXIT_FAILURE);} +} + +/******************************************************************************/ + +LOCAL void chkparam P_((void)); +LOCAL void chkparam () +{ + if ((TB_WIDTH != 2) && (TB_WIDTH != 4)) + chk_err("chkparam: Width parameter is illegal."); + if ((TB_WIDTH == 2) && (TB_POLY & 0xFFFF0000L)) + chk_err("chkparam: Poly parameter is too wide."); + if ((TB_REVER != FALSE) && (TB_REVER != TRUE)) + chk_err("chkparam: Reverse parameter is not boolean."); +} + +/******************************************************************************/ + +LOCAL void gentable P_((void)); +LOCAL void gentable () +{ + WR("/*****************************************************************/\n"); + WR("/* */\n"); + WR("/* CRC LOOKUP TABLE */\n"); + WR("/* ================ */\n"); + WR("/* The following CRC lookup table was generated automagically */\n"); + WR("/* by the Rocksoft^tm Model CRC Algorithm Table Generation */\n"); + WR("/* Program V1.0 using the following model parameters: */\n"); + WR("/* */\n"); + WP("/* Width : %1lu bytes. */\n", + (ulong) TB_WIDTH); + if (TB_WIDTH == 2) + WP("/* Poly : 0x%04lX */\n", + (ulong) TB_POLY); + else + WP("/* Poly : 0x%08lXL */\n", + (ulong) TB_POLY); + if (TB_REVER) + WR("/* Reverse : TRUE. */\n"); + else + WR("/* Reverse : FALSE. */\n"); + WR("/* */\n"); + WR("/* For more information on the Rocksoft^tm Model CRC Algorithm, */\n"); + WR("/* see the document titled \"A Painless Guide to CRC Error */\n"); + WR("/* Detection Algorithms\" by Ross Williams */\n"); + WR("/* (ross@guest.adelaide.edu.au.). This document is likely to be */\n"); + WR("/* in the FTP archive \"ftp.adelaide.edu.au/pub/rocksoft\". */\n"); + WR("/* */\n"); + WR("/*****************************************************************/\n"); + WR("\n"); + switch (TB_WIDTH) + { + case 2: WR("unsigned short crctable[256] =\n{\n"); break; + case 4: WR("unsigned long crctable[256] =\n{\n"); break; + default: chk_err("gentable: TB_WIDTH is invalid."); + } + chk_err(""); + + { + int i; + cm_t cm; + char *form = (TB_WIDTH==2) ? "0x%04lX" : "0x%08lXL"; + int perline = (TB_WIDTH==2) ? 8 : 4; + + cm.cm_width = TB_WIDTH*8; + cm.cm_poly = TB_POLY; + cm.cm_refin = TB_REVER; + + for (i=0; i<256; i++) + { + WR(" "); + WP(form,(ulong) cm_tab(&cm,i)); + if (i != 255) WR(","); + if (((i+1) % perline) == 0) WR("\n"); + chk_err(""); + } + + WR("};\n"); + WR("\n"); + WR("/*****************************************************************/\n"); + WR("/* End of CRC Lookup Table */\n"); + WR("/*****************************************************************/\n"); + WR(""); + chk_err(""); +} +} + +/******************************************************************************/ + +main () +{ + printf("\n"); + printf("Rocksoft^tm Model CRC Algorithm Table Generation Program V1.0\n"); + printf("-------------------------------------------------------------\n"); + printf("Output file is \"%s\".\n",TB_FILE); + chkparam(); + outfile = fopen(TB_FILE,"w"); chk_err(""); + gentable(); + if (fclose(outfile) != 0) + chk_err("main: Couldn't close output file."); + printf("\nSUCCESS: The table has been successfully written.\n"); +} + +/******************************************************************************/ +/* End of crctable.c */ +/******************************************************************************/ + +20. Summary +----------- +This document has provided a detailed explanation of CRC algorithms +explaining their theory and stepping through increasingly +sophisticated implementations ranging from simple bit shifting through +to byte-at-a-time table-driven implementations. The various +implementations of different CRC algorithms that make them confusing +to deal with have been explained. A parameterized model algorithm has +been described that can be used to precisely define a particular CRC +algorithm, and a reference implementation provided. Finally, a program +to generate CRC tables has been provided. + +21. Corrections +--------------- +If you think that any part of this document is unclear or incorrect, +or have any other information, or suggestions on how this document +could be improved, please context the author. In particular, I would +like to hear from anyone who can provide Rocksoft^tm Model CRC +Algorithm parameters for standard algorithms out there. + +A. Glossary +----------- +CHECKSUM - A number that has been calculated as a function of some +message. The literal interpretation of this word "Check-Sum" indicates +that the function should involve simply adding up the bytes in the +message. Perhaps this was what early checksums were. Today, however, +although more sophisticated formulae are used, the term "checksum" is +still used. + +CRC - This stands for "Cyclic Redundancy Code". Whereas the term +"checksum" seems to be used to refer to any non-cryptographic checking +information unit, the term "CRC" seems to be reserved only for +algorithms that are based on the "polynomial" division idea. + +G - This symbol is used in this document to represent the Poly. + +MESSAGE - The input data being checksummed. This is usually structured +as a sequence of bytes. Whether the top bit or the bottom bit of each +byte is treated as the most significant or least significant is a +parameter of CRC algorithms. + +POLY - This is my friendly term for the polynomial of a CRC. + +POLYNOMIAL - The "polynomial" of a CRC algorithm is simply the divisor +in the division implementing the CRC algorithm. + +REFLECT - A binary number is reflected by swapping all of its bits +around the central point. For example, 1101 is the reflection of 1011. + +ROCKSOFT^TM MODEL CRC ALGORITHM - A parameterized algorithm whose +purpose is to act as a solid reference for describing CRC algorithms. +Typically CRC algorithms are specified by quoting a polynomial. +However, in order to construct a precise implementation, one also +needs to know initialization values and so on. + +WIDTH - The width of a CRC algorithm is the width of its polynomical +minus one. For example, if the polynomial is 11010, the width would be +4 bits. The width is usually set to be a multiple of 8 bits. + +B. References +------------- +[Griffiths87] Griffiths, G., Carlyle Stones, G., "The Tea-Leaf Reader +Algorithm: An Efficient Implementation of CRC-16 and CRC-32", +Communications of the ACM, 30(7), pp.617-620. Comment: This paper +describes a high-speed table-driven implementation of CRC algorithms. +The technique seems to be a touch messy, and is superceded by the +Sarwete algorithm. + +[Knuth81] Knuth, D.E., "The Art of Computer Programming", Volume 2: +Seminumerical Algorithms, Section 4.6. + +[Nelson 91] Nelson, M., "The Data Compression Book", M&T Books, (501 +Galveston Drive, Redwood City, CA 94063), 1991, ISBN: 1-55851-214-4. +Comment: If you want to see a real implementation of a real 32-bit +checksum algorithm, look on pages 440, and 446-448. + +[Sarwate88] Sarwate, D.V., "Computation of Cyclic Redundancy Checks +via Table Look-Up", Communications of the ACM, 31(8), pp.1008-1013. +Comment: This paper describes a high-speed table-driven implementation +for CRC algorithms that is superior to the tea-leaf algorithm. +Although this paper describes the technique used by most modern CRC +implementations, I found the appendix of this paper (where all the +good stuff is) difficult to understand. + +[Tanenbaum81] Tanenbaum, A.S., "Computer Networks", Prentice Hall, +1981, ISBN: 0-13-164699-0. Comment: Section 3.5.3 on pages 128 to 132 +provides a very clear description of CRC codes. However, it does not +describe table-driven implementation techniques. + + +C. References I Have Detected But Haven't Yet Sighted +----------------------------------------------------- +Boudreau, Steen, "Cyclic Redundancy Checking by Program," AFIPS +Proceedings, Vol. 39, 1971. + +Davies, Barber, "Computer Networks and Their Protocols," J. Wiley & +Sons, 1979. + +Higginson, Kirstein, "On the Computation of Cyclic Redundancy Checks +by Program," The Computer Journal (British), Vol. 16, No. 1, Feb 1973. + +McNamara, J. E., "Technical Aspects of Data Communication," 2nd +Edition, Digital Press, Bedford, Massachusetts, 1982. + +Marton and Frambs, "A Cyclic Redundancy Checking (CRC) Algorithm," +Honeywell Computer Journal, Vol. 5, No. 3, 1971. + +Nelson M., "File verification using CRC", Dr Dobbs Journal, May 1992, +pp.64-67. + +Ramabadran T.V., Gaitonde S.S., "A tutorial on CRC computations", IEEE +Micro, Aug 1988. + +Schwaderer W.D., "CRC Calculation", April 85 PC Tech Journal, +pp.118-133. + +Ward R.K, Tabandeh M., "Error Correction and Detection, A Geometric +Approach" The Computer Journal, Vol. 27, No. 3, 1984, pp.246-253. + +Wecker, S., "A Table-Lookup Algorithm for Software Computation of +Cyclic Redundancy Check (CRC)," Digital Equipment Corporation +memorandum, 1974. + diff --git a/2000/anderson/Makefile b/2000/anderson/Makefile index 7fcd62db5..7dfa31eda 100644 --- a/2000/anderson/Makefile +++ b/2000/anderson/Makefile @@ -114,8 +114,8 @@ OBJ= ${PROG}.o DATA= TARGET= ${PROG} # -ALT_OBJ= ${PROG}.alt.o -ALT_TARGET= ${PROG}.alt +ALT_OBJ= +ALT_TARGET= ################# diff --git a/2000/anderson/README.md b/2000/anderson/README.md index 01f630966..1c2c3ee97 100644 --- a/2000/anderson/README.md +++ b/2000/anderson/README.md @@ -1,10 +1,10 @@ # Best Use of Flags -Glyn Anderson -Jl. Raya Serang KM 18.2 -Desa Bojong -Cikupa, Tangerang, 15710 -Indonesia +Glyn Anderson +Jl. Raya Serang KM 18.2 +Desa Bojong +Cikupa, Tangerang, 15710 +Indonesia ## To build: @@ -13,10 +13,8 @@ make ``` [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) changed this entry to -use `fgets()` instead of `gets()` to make it safer and to prevent warnings from -showing up at linking or runtime. Thank you Cody! - -For the original source [anderson.alt.c](anderson.alt.c) see below. +use `fgets()` instead of `gets()` to make it safer and to prevent annoying +warnings from showing up at linking or runtime. Thank you Cody! ## To run: @@ -31,17 +29,6 @@ echo something | ./anderson echo Obfuscate | ./anderson ``` -### Alternate code: - -For the original version that uses `gets()` try: - - -```sh -make alt -``` - -Use `anderson.alt` as you would `anderson`. - ## Judges' remarks: This small program might be a nice addition to a digital personal @@ -49,7 +36,7 @@ organizer; just in case you are stranded on a desert island and need to signal your distress to passing ships. The obfuscation in this program is truly masterful. The program is -very cleverly obscured without the use of a single #define! +very cleverly obscured without the use of a single `#define`! Reformatting this program by hand :-) is the easiest way to understand what is going on. @@ -65,17 +52,19 @@ output as a depiction of a person holding two flags, using only ASCII characters (semaphore smileys, if you will). For example, given the input "Hello, world!", the output will be: - <> <> <> <> <> <> - _() ()/ ()/ ()/ _\) () (/_ _\) - [] /^ |^^ /^^ /^^ [] ^^ |^^| ^^ [] [] ^^ - <>[ [][ <>][ <>][ ][ [][] ][ ][ +``` + <> <> <> <> <> <> + _() ()/ ()/ ()/ _\) () (/_ _\) +[] /^ |^^ /^^ /^^ [] ^^ |^^| ^^ [] [] ^^ + <>[ [][ <>][ <>][ ][ [][] ][ ][ - <> [] - _()_ ()/ |() () - [] ^^ [] /^^ ^^| |^^| - ][ <>][ ][] [][] + <> [] + _()_ ()/ |() () +[] ^^ [] /^^ ^^| |^^| + ][ <>][ ][] [][] +``` The program is obfuscated without the use of the preprocessor or any special compilation parameters. In fact, the program doesn't even @@ -87,7 +76,7 @@ statements to format the code properly.) There is a single string constant which encodes the flag positions and other data needed for drawing the semaphore codes. -The preprocessor will provide no help in un-obfuscating this code, and a +The preprocessor will provide no help in de-obfuscating this code, and a C beautifier won't get you very far either. You just have to crunch through it. diff --git a/2000/bellard/README.md b/2000/bellard/README.md index 8ce4abc40..e953e249d 100644 --- a/2000/bellard/README.md +++ b/2000/bellard/README.md @@ -1,11 +1,10 @@ # Most Specific Output - Fabrice Bellard - 451 chemin du mas de Matour - 34790 Grabels - France - - http://www.enst.fr/~bellard +Fabrice Bellard +451 chemin du mas de Matour +34790 Grabels +France + ## To build: @@ -27,16 +26,18 @@ Do. Or do not. There is no try. :-) ## Judges' remarks: -This code is an nice compact example of a Modular Fast Fourier Transform. -While its output is very specific, the internal FFT has a wide variety -of uses. +This code is a nice compact example of a Modular Fast Fourier Transform. While +its output is very specific, the internal FFT has a wide variety of uses. Can you modify this code to produce primes such as `23523*2^70000-1, 48594^65536+1` or `6917!-1`? -### Alternate code: +NOTE: as bigger primes are found as time goes by this program no longer prints +the biggest prime once noted by the author below. -This program printed the biggest known prime number (2^6972593-1) +## Author's comments: + +This program prints the biggest known prime number (`2^6972593-1`) in base 10. It requires a few minutes. It uses a Modular Fast Fourier Transform to compute this number in a reasonable amount of time (the usual method would take ages !). diff --git a/2000/bmeyer/.gitignore b/2000/bmeyer/.gitignore index 79a0ac3fc..b6a5b0192 100644 --- a/2000/bmeyer/.gitignore +++ b/2000/bmeyer/.gitignore @@ -1 +1,2 @@ bmeyer +lavabus.glic diff --git a/2000/bmeyer/README.md b/2000/bmeyer/README.md index c7ce2be7d..2c93fdfa1 100644 --- a/2000/bmeyer/README.md +++ b/2000/bmeyer/README.md @@ -1,11 +1,11 @@ # Best Utility - Bernd Meyer - Monash University, Melbourne, Australia - 1/832 Blackburn Rd - Clayton, VIC 3168 - Australia - http://byron.csse.monash.edu.au/ +Bernd Meyer +Monash University, Melbourne, Australia +1/832 Blackburn Rd +Clayton, VIC 3168 +Australia + ## To build: @@ -27,7 +27,7 @@ In a video window (white text on black background): ./bmeyer < michael.pgm > michael.glic ``` -Compare the michael.pgm to the screen output. +Compare the `michael.pgm` to the screen output. To test that you are compressing and decompressing the same way the author was, try: @@ -42,8 +42,8 @@ Also try in a reverse video window: ./bmeyer < michael.pgm 2>/dev/null | ./bmeyer > new.pgm ``` -Compare the michael.pgm to the screen output. Compare the new.pgm file -to the michael.pgm file. +Compare the [michael.pgm](michael.pgm) to the screen output. Compare the +`new.pgm` file to the [michael.pgm](michael.pgm) file. Create a large reverse video xterm, say 200 columns wide and try: @@ -63,7 +63,8 @@ Decompress that smaller glic-file: ./bmeyer -2 200 < lavabus.glic2 > new.pgm ``` -Compare the new.pgm file to the lavabus.pgm file by viewing them. +Compare the `new.pgm` file to the [lavabus.pgm](lavabus.pgm) file by viewing +them. ## Judges' remarks: @@ -94,25 +95,23 @@ to set your FPU to use 64 bit mode. See the extra build lines in the Makefile, and read the author's remarks below. If you cannot work out how to get into 64 bit mode, you can -try using -ffloat-store if you compile with GCC (this may have +try using `-ffloat-store` if you compile with GCC (this may have a performance penalty). The resulting binary will have a good chance to produce portable files, but due to the resulting double-rounding (first internally to 80 bit, then to 64 bit on writing the value to memory), there is a small but very real chance any given file produced might not be portable. -The makefile defaults to -O3 and no `asm()` call. +The [Makefile](Makefile) defaults to `-O3` and no `asm()` call. ## Author's remarks: -GLICBAWLS +This program is called `GLICBAWLS` -A) Function -=========== +#### Function -"GLICBAWLS" stands for: - - "Grey Level Image Compression By Adaptive Weighted Least Squares". +`GLICBAWLS` stands for "Grey Level Image Compression By Adaptive Weighted Least +Squares". And that's exactly what this program does --- feed it a .PGM file (either raw [i.e. P5] or ascii [i.e. P2]) on stdin, and it will @@ -131,7 +130,7 @@ and then ./bmeyer < michael.glic > michael.decoded.pgm ``` -As it turns out, glicbawls compresses greyscale images (or, more +As it turns out, `glicbawls` compresses greyscale images (or, more precisely, "natural" greyscale images) better than any other program I am aware of (with the exception of the not-yet-published program developed for my PhD thesis). Of course, this might take @@ -142,25 +141,25 @@ output to stderr (assuming white text on black background). If you have trouble recognizing the image, try squinting at it ;-). If you still have trouble, simply use a terminal or xterm with -more than 80 columns, and tell glicbawls about it by giving the +more than 80 columns, and tell `glicbawls` about it by giving the number of columns as an argument. For example ```sh ./bmeyer 260 lavabus.glic ``` -will allow glicbawls to use up to 260 columns, which makes things +will allow `glicbawls` to use up to 260 columns, which makes things much more recognizable. Still running out of space? Need to compress those images just a tad more? And maybe you can handle some loss due to the -compression? If so, you can use glicbawls' "near lossless" +compression? If so, you can use `glicbawls`' "near lossless" compression mode. In that mode, the decoded pixel values are -allowed to differ from tbe originals, but there is an upper limit +allowed to differ from the originals, but there is an upper limit on the magnitude of the difference. For example, if a maximum error of 2 is allowed, an original pixel value of 37 could be decoded as 35,36,37, 38 or 39. In order to use this mode, simply -give the maximum allowed error as an argument, with a dash ('-') +give the maximum allowed error as an argument, with a dash (`-`) before it. For example ```sh @@ -183,8 +182,8 @@ terminal for the progress display, and will decompress the result on such a terminal. -But wait, there is more --- you can also feed glicbawls .PPM files -(i.e. colour images), raw or ascii, your choice. Glicbawls will +But wait, there is more --- you can also feed `glicbawls` .PPM files +(i.e. colour images), raw or ascii, your choice. `Glicbawls` will compress and decompress them just fine. However, it only does "reasonably well" on them; It beats PNG easily, but there are certainly programs out there that can compress colour images @@ -192,61 +191,54 @@ considerably better. And don't even *think* about using it for so-called "artistic" images (i.e. anything that wasn't scanned from a photo or camera).... -***************************************************************** -* * -* WARNING WARNING WARNING WARNING WARNING WARNING WARNING * -* * -* * -* Glicball is rather CPU and FPU intensive. Don't * -* run it on anything slow. Things start to be * -* usable around 300+MHz, with 600+ being highly * -* desirable. * -* * -***************************************************************** +### WARNING + + +`Glicball` is rather CPU and FPU intensive. Don't run it on anything slow. +Things start to be usable around 300+MHz, with 600+ being highly desirable. -B) Compile Instructions -======================= -Unlike most compression program, glicbawls makes heavy use of +### Compile Instructions + +Unlike most compression program, `glicbawls` makes heavy use of floating point maths --- and not all FPUs are created equal. Most importantly, the x86 and 68k FPUs use 80 bit floating point formats internally, while most other processors use IEEE 64 bit formats by default. If not taken care of, this means that a -glicbawls file compressed on one CPU cannot generally be +`glicbawls` file compressed on one CPU cannot generally be decompressed on another. Fortunately, just about all current FPUs can be put into IEEE 64 bit mode (or at least something close enough for -glicbawls). Unfortunately, there is no standard way of doing +`glicbawls`). Unfortunately, there is no standard way of doing so. For this reason, the build file contains *three* compile lines; One for machines that already use 64 bit mode by default (most RISC processors), one for linux/x86 machines using libc4, libc5 or glibc2.0, and one for linux/x86 machines using glibc2.1 -(glibc2.1 no longer exports the __setfpucw function, necessitating -the use of gcc inline assembly. *Grumble*). +(glibc2.1 no longer exports the `__setfpucw()` function, necessitating +the use of gcc inline assembly. \*Grumble\*). So, if you are building on a machine that does not, by default, -use IEEE 64 bit floating point doubles, you'll have to define Y to +use IEEE 64 bit floating point doubles, you'll have to define `Y` to be a command that switches it into that mode. If you fail to do -so, your glicbawls executable will still be able to decompress its +so, your `glicbawls` executable will still be able to decompress its own compressed files, but you may be unable to exchange files with -glicbawls on other machines. +`glicbawls` on other machines. -C) Obfuscation -============== +### Obfuscation Most of the obfuscation of this program was driven by the -desperate struggle to fit all of glicbawls' features into code +desperate struggle to fit all of `glicbawls`' features into code that fits the IOCCC's size limits. All identifiers names are single-character, which was only possible by ruthless exploitation -of scope. There is a function M() that handles nearly all input +of scope. There is a function `M()` that handles nearly all input from stdin, handles all output to stdout, and also recursively calculates one of the mathematical expressions needed for error -modelling. There is a function that calculates (A^(-1)*b)*x with A -a matrix and b and x being vectors, and does so in a very +modelling. There is a function that calculates `(A^(-1)*b)*x` with `A` +being a matrix and `b` and `x` being vectors, and does so in a very efficient way --- but one would be hard pressed to find it. There is an arithmetic coder that is even less recognizable. A lot of loop variables don't get initialized, but instead the code is @@ -257,7 +249,7 @@ meaning all the time, and the differences between compressing and decompressing are handled in rather subtle ways all over the program. The string that holds the ascii values for displaying the progress image doubles as a description on how to find a pixel's -causal neighbours. And then there are a few #define's that really +causal neighbours. And then there are a few `#define`s that really are just in there to save a few characters, but as an added "benefit" make the source ever more unreadable. @@ -265,31 +257,30 @@ In short --- running it through the preprocessor and the pretty-printer will give you something that looks slightly less like line noise and slightly more like a C program, but unless you are a true wizard, it is unlikely to gain you any insights into -what is actually going on....[0] +what is actually going on....\[0\] -D) Bugs, Assumptions and TODOs -============================== +### Bugs, Assumptions and TODOs -Glicbawls assumes that characters are 8 bit wide, and that the +`Glicbawls` assumes that characters are 8 bit wide, and that the character set used is ASCII. If one of these isn't true, all hell will break loose. -The .PGM headers are not checked very thoroughly --- glicbawls +The .PGM headers are not checked very thoroughly --- `glicbawls` will happily try to encode lots of files that it shouldn't touch. The old adage of "garbage in, garbage out" holds in that -case. Furthermore, even if glicbawls detects an incorrect input, +case. Furthermore, even if `glicbawls` detects an incorrect input, it fails to provide a meaningful error message, and instead simply aborts. -When decompressing a near-losslessy encoded image, the maximum +When decompressing a near-lossless encoded image, the maximum allowed error is required as a command line parameter. This should really be saved in the compressed file! -Glicbawls relies on the decimal representation of all integers +`Glicbawls` relies on the decimal representation of all integers having less than 255 digits. While ANSI C does not guarantee this, it seems rather unlikely that anyone in the foreseeable future -would use images with 10^255 rows, columns or different levels of +would use images with `10^255` rows, columns or different levels of grey. Also, it is assumed that any integer used can be cast to a double and back without loss of precision. This limits the number of rows, columns and grey levels to 9 quintillion, which should @@ -302,14 +293,13 @@ million in a lottery. But if it happens to you, don't say I didn't warn you! Instead, go out and buy a lightning rod and a lottery ticket ;-) -At one point, a pointer to int is used as the target of a "%1[#]" +At one point, a pointer to int is used as the target of a `"%1[#]"` conversion in a scanf, which makes gcc rather unhappy, but shouldn't really cause anyone any trouble. The same goes for a couple of assignments which are used as truth values. -E) Algorithm -============ +### Algorithm An exhaustive explanation of the algorithm used would go beyond the scope of an info file, and would also be quite difficult in @@ -321,11 +311,11 @@ expected value is calculated by creating a least squares predictor of order 12 based on all of the previously encoded/decoded pixels. However, the contribution of each pixel is weighted according to its Manhattan-distance from the current pixel, -D. That weight used is pow(0.8,D). [1][2][3] +D. That weight used is `pow(0.8,D)`. \[1\] \[2\] \[3\] In a similar way, the prediction *errors* for all previous pixels -are combined --- a weighted average (with weight pow(0.7,D)) of +are combined --- a weighted average (with weight `pow(0.7,D)`) of the squares of all previous prediction errors is taken, and the square root of the (appropriately scaled) result is called sigma. @@ -343,22 +333,22 @@ arithmetic decoder provides the information which half the actual value is in. In both cases, the interval borders are adjusted accordingly, the arithmetic coder/decoder updated, and the interval halving repeated until the precise value has been -en/decoded[4]. +en/decoded\[4\]. [0] Yes, this could be seen as a challenge.... -[1] Actually, the weight is pow(0.8,D)/s, where s is the sigma +[1] Actually, the weight is `pow(0.8,D)/s`, where `s` is the sigma used for en/decoding the particular previous pixel. Dividing - by s is a rather arbitrary action justified only by the + by `s` is a rather arbitrary action justified only by the improvement in results. Mathematically, I can only justify - dividing by s^2, or not dividing at all.... + dividing by `s^2`, or not dividing at all.... [2] Obviously, these least squares predictors are not calculated from scratch for each pixel. Some clever reuse of earlier results allows O(1) calculation, rather than the - O(previous_rows*columns) this description would suggest. + `O(previous_rows*columns)` this description would suggest. [3] As anyone who has ever tried local least squares knows from bitter experience, there is a lot of numerical instability - associated with them. So glicbawls adds a bias towards an + associated with them. So `glicbawls` adds a bias towards an averaging predictor to the equation system the least squares predictor is calculated from. The weight that is given to this bias is constantly adjusted throughout coding/decoding, @@ -370,31 +360,29 @@ en/decoded[4]. iteration ends as soon as the interval is small enough to guarantee decoding within the requested maximum error. -#################################################################### -Photo Credit: +### Photo Credit: - Lavabus was taken by the judge, Landon Curt Noll. Michael was - provided by the author. Lenna is a 1972 Playboy centerfold. +[Lavabus](lavabus.pgm) was taken by the judge, Landon Curt Noll. +[Michael](michael.pgm) was provided by the author. [Lenna](lenna.glic) is a +1972 Playboy centerfold. - michael.pgm +- [michael.pgm](michael.pgm) - The author's Godchild and nephew. + The author's Godchild and nephew. - lavabus.pgm +- [lavabus.pgm](lavabus.pgm) - A bus that was trapped by lava from Kilauea volcano in - Hawaii, USA. Nobody was in the bus at the time, BTW. - Photo date: 1981. + A bus that was trapped by lava from Kilauea volcano in Hawaii, US. Nobody + was in the bus at the time, BTW. Photo date: 1981. - lenna.glic +- [lenna.glic](lenna.glic) - A November 1972 Playboy centerfold was scanned in long ago and - has been used for image compression research since then. Playboy - originally threatened to prosecute unauthorized use, but - eventually granted that, having been in use for image compression - testing for so long, it was now a useful benchmark. (Note: This - picture doesn't show very much.) + A November 1972 Playboy centerfold was scanned in long ago and has been used + for image compression research since then. Playboy originally threatened to + prosecute unauthorized use, but eventually granted that, having been in use + for image compression testing for so long, it was now a useful benchmark. + (Note: This picture doesn't show very much.) ## Copyright and CC BY-SA 4.0 License: diff --git a/2000/briddlebane/README.md b/2000/briddlebane/README.md index fd3440e1c..a1e53fbbd 100644 --- a/2000/briddlebane/README.md +++ b/2000/briddlebane/README.md @@ -1,12 +1,12 @@ # Best Abuse of User -Moxen N. Briddlebane -24 Oxtree Ave. -The Xoemn, MN 68214 +Moxen N. Briddlebane +24 Oxtree Ave. +The Xoemn, MN 68214 -Lord Zarbon -24 Oxtree Ave. -The Xoemn, MN 68214 +Lord Zarbon +24 Oxtree Ave. +The Xoemn, MN 68214 ## To build: @@ -22,9 +22,9 @@ make ## Try: -```sh -echo "Do or do not. There is no try." -``` +For some fun every time you log in try running this from your `.bashrc` or +equivalent file! + ## Judges' remarks: @@ -37,11 +37,11 @@ Can you find out how it stores the insult strings? Can you then take an insult and figure out when it will be uttered? [sc] The code also contains a buffer overflow bug which I have fixed! -The array size of "s" should be 1079 characters long. (From 0 to 1078 +The array size of `s` should be 1079 characters long. (From 0 to 1078 inclusive!). Without this it results in an error in the encoding of "decrepit" -- For a 32bit little endian machine using GCC (because of the way it assigns variables to memory) it will terminate "decrepit" -with the character '\200' (the last value of F) instead of '\0'. +with the character `'\200'` (the last value of `F`) instead of `'\0'`. ## Author's remarks: @@ -60,8 +60,8 @@ mechanics of programming. What is particularly disturbing is the curious method of insult-encoding employed by this program. Furthermore, it is ambiguous how said data is arranged and why it is necessary to resort to trigonometric functions to handle -it. One of the real mysteries involves the numbers "114" and -"2", which are, according to Lord Zarbon, very deliberate. +it. One of the real mysteries involves the numbers `114` and +`2`, which are, according to Lord Zarbon, very deliberate. ## Copyright and CC BY-SA 4.0 License: diff --git a/2000/dhyang/README.md b/2000/dhyang/README.md index 0b1cb8869..f76da504d 100644 --- a/2000/dhyang/README.md +++ b/2000/dhyang/README.md @@ -1,12 +1,11 @@ # Best Layout -Don Yang -UCSD -259 E. Bellbrook St. -Covina, CA 91722 -USA - -http://omoikane.cjb.net +Don Yang +UCSD +259 E. Bellbrook St. +Covina, CA 91722 +US + ## To build: @@ -58,22 +57,22 @@ them with cool layout! For your enjoyment: -1. Compile saitou.c -2. Run a.out and pipe output to another .c file +1. Compile [dhyang.c](dhyang.c). +2. Run `./dhyang` and pipe output to another .c file 3. Compile that file 4. Repeat steps 2 and 3 until eventually the output cycles -To interpret the output: the saitou.c is an image of Saitou Hajime, -which eventually generates three sources files that are images of -"aku soku zan" (sin swift slay), Saitou's motto ;) +To interpret the output: the [dhyang.c](dhyang.c.c) is an image of Saitou +Hajime, which eventually generates three sources files that are images of "aku +soku zan" (sin swift slay), Saitou's motto ;) For best viewing, set tab spaces to 8 characters, and set your terminal fonts to as close to square as possible. I hate to do this but you know, size... -saitou.c and all its output compiles with gcc if your OS uses ASCII -character set. No file is included and all functions assume default -int return type (a source of compile warnings) +[dhyang.c](dhyang.c) and all its output compiles with gcc if your OS uses ASCII +character set. No file is included and all functions assume default int return +type (a source of compile warnings). ## Copyright and CC BY-SA 4.0 License: diff --git a/2000/dlowe/README.md b/2000/dlowe/README.md index b0d65f901..a49e6b510 100644 --- a/2000/dlowe/README.md +++ b/2000/dlowe/README.md @@ -1,11 +1,9 @@ # Worst Abuse of the Rules -David Lowe -1224 11th Avenue -San Francisco, California, 94122 -USA - -http://pootpoot.com/~dlowe/ +David Lowe +1224 11th Avenue +San Francisco, California, 94122 +US ## To build: @@ -22,6 +20,7 @@ perl -MConfig -e 'print "$Config{archlibexp}/CORE\n"' [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed this to compile with more recent perl versions; the symbol now `PL_na` was once `na`. He notes that this entry crashes under macOS but it works under linux after this change. +Thank you Cody for your assistance! ## To run: @@ -41,8 +40,8 @@ echo "13 14 15 16 17 + - * / p" | ./dlowe When this entry was submitted the rules of the IOCCC did not prohibit the use of embedded language interpreters. The judges considered disqualifying this entry because of the use of perl, but on the other -hand it qualifies as the Worst Abuse of the Rules. As a previous winner -* David Lowe continues to inflict the highest quality "poot" on the +hand it qualifies as the Worst Abuse of the Rules. As a previous winner\* +David Lowe continues to inflict the highest quality "poot" on the Judges. The program also contains an undocumented command for Chad and Chongo. @@ -53,30 +52,33 @@ of the submitters hidden until all the prize winners have been selected. ## Author's remarks: -### Usage: +### Usage ./dlowe [file ...] -### Synopsis: +### Synopsis -This is a reverse polish calculator, loosely based on the dc(1) unix +This is a reverse polish calculator, loosely based on the `dc(1)` unix calculator. -# Syntax: +# Syntax -This program understands the following dc(1) commands: +This program understands the following `dc(1)` commands: - p prints the top stack value without altering the stack. - P prints the top stack value, removing it from the stack, and - doesn't print a trailing newline. - f prints the contents of the stack, one number per line, - without modifying it. - c clears the stack. - d pushes a copy of the top stack value onto the stack. - r reverses the order of the top two stack values. +``` +p prints the top stack value without altering the stack. +P prints the top stack value, removing it from the stack, and + doesn't print a trailing newline. +f prints the contents of the stack, one number per line, + without modifying it. +c clears the stack. +d pushes a copy of the top stack value onto the stack. +r reverses the order of the top two stack values. +``` And the following arithmetic operators are supported: +``` + Pops 2 values and pushes their sum. - Pops 2 values and pushes the result of subtracting the first from the second. @@ -87,14 +89,15 @@ And the following arithmetic operators are supported: to the power of the first. % Pops 2 values and pushes the remainder of the division that / would do. +``` The precision and range are double, like it or not, except that the -modulus operator actually returns (p1 - (p2 * (p1 / p2))), but with +modulus operator actually returns `(p1 - (p2 * (p1 / p2)))`, but with the innermost division calculated at integer precision. This is -usually what you expect (e.g. echo "12 8 % p" | ./dlowe == 4) +usually what you expect (e.g. `echo "12 8 % p" | ./dlowe == 4`) Commands are read from stdin or from a list of files named on -the command line. Unlike dc(1), multiple commands on the same line +the command line. Unlike `dc(1)`, multiple commands on the same line must be space separated. Commands are only executed when a newline or EOF is encountered. @@ -153,9 +156,9 @@ error reporting. Unfortunately, Perl is an evolving beast - that includes the embedding API and the XS API. The code was developed under -Perl 5.005_03, successfully tested against Perl 5.6.0, Perl 5.005_02 -and Perl 5.004_04, and according to the version delta documentation, -should work as-is with Perl 5.002 and later (which has been around +`Perl 5.005_03`, successfully tested against `Perl 5.6.0`, `Perl 5.005_02` +and `Perl 5.004_04`, and according to the version delta documentation, +should work as-is with Perl 5.002` and later (which has been around since February 1996). To clarify - it's not the Perl code itself that may be non-portable, it's the C code for embedding Perl and for calling C from Perl. @@ -169,7 +172,7 @@ by slight misconfigurations of Perl on your system. Some compilers also complain that "third argument of `main' is deprecated" or something to that effect. But in Perl prior to -5.6.0, the header file "proto.h" actually had a prototype for main, +`5.6.0`, the header file "proto.h" actually had a prototype for main, so applications which embed Perl must use the three argument form of main. @@ -182,52 +185,52 @@ say, camels and humps. ### Obfuscated? -. Reverse polish notation is pretty strange, in and of itself. +- Reverse polish notation is pretty strange, in and of itself. -. The layout of the program is three roughly symmetrical "stacks" +- The layout of the program is three roughly symmetrical "stacks" of code. This layout is quite sensitive in places - my C indenter actually breaks the code by inserting spaces in certain places. -. Anyone who has ever programmed in Perl can attest to the fact that +- Anyone who has ever programmed in Perl can attest to the fact that it is particularly well-suited to obfuscation; thus, the Perl is obfuscated. (Here's my favorite legal Perl from this program: -'_:$_=<>;' - but '$SS[$#SS]-=$SS[$#SS-1]' isn't bad, either). +`_:$_=<>;` - but `$SS[$#SS]-=$SS[$#SS-1]` isn't bad, either). -. I've eschewed traditional branch and loop structures such as -'if' and 'for', in favor of their oft-neglected cousins, 'goto' -and '?:', in both the Perl and C code. +- I've eschewed traditional branch and loop structures such as +`if` and `for`, in favor of their oft-neglected cousins, `goto` +and `?:`, in both the Perl and C code. -. I've used some highly magical Perl incantations, such as symbolic -references, the 'goto &NAME' syntax, AUTOLOAD for exception handling, -and abuse of the default scalar ($_). +- I've used some highly magical Perl incantations, such as symbolic +references, the `goto &NAME` syntax, `AUTOLOAD` for exception handling, +and abuse of the default scalar (`$_`). -. I've also deliberately used Perl syntax that is very much unlike -C syntax: the &NAME rather than NAME() function calling syntax, -leaving off parentheses wherever possible, using print() instead -of printf(), and using the English style logic operators 'and' and -'or' rather than '&&' and '||', for example. +- I've also deliberately used Perl syntax that is very much unlike +C syntax: the `&NAME` rather than `NAME()` function calling syntax, +leaving off parentheses wherever possible, using `print()` instead +of `printf()`, and using the English style logic operators `and` and +`or` rather than `&&` and `||`, for example. -. The fact that all the Perl code is in double-quotes doesn't lend +- The fact that all the Perl code is in double-quotes doesn't lend any readability to the regular expressions and quoted strings therein. -. The points and ways in which C and Perl connect are *really* +- The points and ways in which C and Perl connect are *really* obscure. They're also incredibly poorly documented, as they're primarily used in machine-generated code. However, there's a -wealth of example code on CPAN (www.cpan.org). +wealth of example code on [CPAN (www.cpan.org)](https://www.cpan.org). -. The Perl API functions are almost all macros, so you will probably +- The Perl API functions are almost all macros, so you will probably find that preprocessor expansion will only make things worse. They -also have helpful, verbose names like SvNV, SvIV, and newSVpv. I +also have helpful, verbose names like `SvNV`, `SvIV`, and `newSVpv`. I couldn't have done better myself! -. Figuring out how the mathematical C functions get called is a bit +- Figuring out how the mathematical C functions get called is a bit tricky. Note the lack of explicit switching based on command input. -. Because of the "interesting" way that commands are interpreted, +- Because of the "interesting" way that commands are interpreted, all of the commands have synonyms. For example, if you find it -easier to remember, '=' is synonymous with 'd'. This is makes it +easier to remember, `=` is synonymous with `d`. This also makes it possible to write (even more) obfuscated reverse polish commands (I figure this explanation moves the synonyms from 'bug' to 'feature'!) @@ -235,13 +238,15 @@ possible to write (even more) obfuscated reverse polish commands . The first IOCCC entry with an "easter egg"?... -Aside: on unobfuscated Perl +### Aside: on unobfuscated Perl + My original intent was to write obfuscated C and crystal-clear Perl, to highlight my bending of the rules. Unfortunately, Perl really doesn't lend itself to crystal-clear code... -Bending the rules? +### Bending the rules? + Well, the rules never state that you can't embed another programming language, but on the other hand, knowing Perl probably isn't high on the list of qualifications for judges... Oh dear, I guess your C @@ -251,7 +256,7 @@ If you don't change the rules, it'll be embedded Ada next year! ### AutoDefend -A. Isn't this the obfuscated C contest? What's this Perl $#_&&$_? +A. Isn't this the obfuscated C contest? What's this Perl `$#_&&$_`? D. Hey, this program *is* 100% C, and does not exec an external Perl interpreter. It simply links against the Perl language library. diff --git a/2000/jarijyrki/.gitignore b/2000/jarijyrki/.gitignore index 85af3a2cd..413994b1a 100644 --- a/2000/jarijyrki/.gitignore +++ b/2000/jarijyrki/.gitignore @@ -1,2 +1,3 @@ jarijyrki myedits.info +outfile.info diff --git a/2000/jarijyrki/Makefile b/2000/jarijyrki/Makefile index 020ebb588..5744b4ebb 100644 --- a/2000/jarijyrki/Makefile +++ b/2000/jarijyrki/Makefile @@ -115,7 +115,7 @@ ENTRY= jarijyrki PROG= ${ENTRY} # OBJ= ${PROG}.o -DATA= sheet1.info +DATA= finance.sheet TARGET= ${PROG} # ALT_OBJ= diff --git a/2000/jarijyrki/README.md b/2000/jarijyrki/README.md index 74d607607..9c5a7b3d9 100644 --- a/2000/jarijyrki/README.md +++ b/2000/jarijyrki/README.md @@ -1,18 +1,16 @@ # Best of Show - Jari Arkko - Kauppalantie 25A7, - 02700 Kauniainen, - Finland - - http://www.arkko.com - - Jyrki Holopainen - Forsellesintie 1-3A10, - 02700 Kauniainen, - Finland - - http://personal.eunet.fi/pp/halo/ +Jari Arkko +Kauppalantie 25A7 +02700 Kauniainen +Finland + + +Jyrki Holopainen +Forsellesintie 1-3A10 +02700 Kauniainen +Finland + ## To build: @@ -38,353 +36,431 @@ You will need a system capable of displaying the results of X Window programs. ## Try: ```sh -./jarijyrki < sheet1.info > myedits.info +./jarijyrki < finance.sheet > myedits.info ``` +Then click on cell `C3` and type in the following: + +``` +C5 C6 C7 @ +``` + +Click on cell `D4` and type in the following: + +``` +C5 C6 C7 ! +``` + +Hit `ESC`. + +Now try running: + +``` +./jarijyrki < myedits.info +``` + +And observe that it matches what you had in the previous run! + +NOTE: changing the dimension parameters (see the authors' comments) renders +existing spreadsheet files unusable. ## Judges' remarks: -This entry is one of those that makes you wonder why some commercial -software needs tens to hundreds of megabytes to install! This entry -does not simply do the basics, it includes graphing features. All this +This entry is one of those that makes you wonder why some commercial software +needs tens to hundreds of megabytesgigabytes to install! This +entry does not simply do the basics, it includes graphing features. All this program needs now is a flight simulator! ## Author's remarks: -1. OVERVIEW +### 1. OVERVIEW -This program is an X-Windows based spreadsheet program. -The main functions it supports are: +This program is an X-Windows based spreadsheet program. The main functions it +supports are: - * Text cells - * Numeric cells - * Arithmetic operations: + - * / - * Pie charts - * Histograms - * Cell editing - * Formula line - * Dynamic recalculation - * Error detection - * Recursion detection - * Movement within the spreadsheet with cursor keys - * Movement within the spreadsheet with mouse - * Scrolling - * Loading and saving spreadsheets - * Visual style configuration +* Text cells +* Numeric cells +* Arithmetic operations: `+` `-` `*` `/` +* Pie charts +* Histograms +* Cell editing +* Formula line +* Dynamic recalculation +* Error detection +* Recursion detection +* Movement within the spreadsheet with arrow keys +* Movement within the spreadsheet with mouse +* Scrolling +* Loading and saving spreadsheets +* Visual style configuration -2. USAGE INSTRUCTIONS +### 2. USAGE INSTRUCTIONS -2.1. Quick Guide +#### 2.1. Quick Guide -Starting: ./jarijyrki < sheet1.info > myedits.info -Stopping: Esc -Movement: Click mouse or cursor keys -Editing: Currently selected cell is always in edit state. - Press any key to add a character at the end of the - formula; press BackSpace to delete the last one. -Formulas: 123.45 - A1 A2 + - B1 B2 - - C1 C2 * - D1 D2 / -Pie charts: A1 A2 A3 ... An @ -Histograms: A1 A2 A3 ... An ! +##### Starting -2.2. Starting and Loading Spreadsheets +```sh +./jarijyrki < finance.sheet > myedits.info +``` + +##### Stopping + +Use the ESC key. + +##### Movement + +Click the mouse or use the arrow keys. + +##### Editing + +The currently selected cell is always in the edit state. Press any key to add a +character at the end of the formula; press backspace to delete the last one. + +##### Formulas + +``` +123.45 +A1 A2 + +B1 B2 - +C1 C2 * +D1 D2 / +``` + +##### Pie charts + +``` +A1 A2 A3 ... +``` + +Finish the formula with `@` to create the pie chart. + +##### Histograms + +``` +A1 A2 A3 ... +``` + +Finish the formula with `!` to create the histogram. + + +#### 2.2. Starting and Loading Spreadsheets To start the spreadsheet program with an existing spreadsheet, use the following command line: - ./jarijyrki < sheet1.info +```sh +./jarijyrki < finance.sheet +``` -The file sheet1.info has been provided as an example. -This file contains a set of financial numbers and two -graphical entities - a pie chart and a histogram - based -on them. We recommend starting the use of the program -from this file, as a way to study and learn the formula -language supported by the program. +The file [finance.sheet](finance.sheet) has been provided as an example. This +file contains a set of financial numbers and two graphical entities - a pie +chart and a histogram - based on them. We recommend starting the use of the +program from this file, as a way to study and learn the formula language +supported by the program. To start the program with an empty sheet, use +```sh ./jarijyrki < /dev/null +``` -[Alternatively, /dev/zero could be used but that may not exist -on all systems.] +Alternatively, `/dev/zero` could be used but that may not exist on all systems. -2.3. Exiting and Saving Spreadsheets +#### 2.3. Exiting and Saving Spreadsheets -Normally the user obviously wants to edit the spreadsheet. -After the spreadsheet program finishes, it outputs the -edited spreadsheet to the standard output. Hence, when -the spreadsheet window has come up, you've made your changes, -and you press the Esc key the program finishes. To save -the results in a file, the following typical command line -would be used: +Normally the user obviously wants to edit the spreadsheet. After the +spreadsheet program finishes, it outputs the edited spreadsheet to the standard +output. Hence, when the spreadsheet window has come up, you've made your +changes, and you press the ESC key the program finishes. To save the results in +a file, the following typical command line would be used: - ./jarijyrki < sheet1.info > myedits.info +```sh +./jarijyrki < finance.sheet > myedits.info +``` -2.4. Visual Overview +#### 2.4. Visual Overview -On top of the window the Formula Area shows the formula (or text) -of the currently selected cell. The program starts with A1 as -being the current cell. Below the Formula Area is the Column -Letters Area: A, B, and so on. Correspondingly, on the left -side of the window is the Row Numbers Area: 1, 2, and so on. -The rest of the window is dedicated to the actual spreadsheet -cells. +On top of the window the Formula Area shows the formula (or text) of the +currently selected cell. The program starts with `A1` as being the current cell. +Below the Formula Area is the Column Letters Area: A, B, and so on. +Correspondingly, on the left side of the window is the Row Numbers Area: 1, 2, +and so on. The rest of the window is dedicated to the actual spreadsheet cells. -The example spreadsheet, sheet1.info, provided with this -program contains two sets of numbers in the visible area -of the spreadsheet. The top set of numbers forms the -product-by-product turnover breakdown of an imaginary -company. Below it is the yearly development of the -company profits. On the top right corner is a pie chart -showing the turnover breakdown in graphical form, and -on the bottom right corner is a histogram showing the -yearly development. If you scroll the window you can -see additional data from the spreadsheet. +The example spreadsheet, [finance.sheet](finance.sheet), provided with this +program contains two sets of numbers in the visible area of the spreadsheet. The +top set of numbers forms the product-by-product turnover breakdown of an +imaginary company. Below it is the yearly development of the company profits. On +the top right corner is a pie chart showing the turnover breakdown in graphical +form, and on the bottom right corner is a histogram showing the yearly +development. If you scroll the window you can see additional data from the +spreadsheet. -2.5. Movement and Scrolling +#### 2.5. Movement and Scrolling -Use cursor keys to move left, right, up, and down among the cells. -[Note that it is not possible to move around the formula; the -formula can only be edited from its end by adding or removing -characters.] You may also click the mouse on a cell to cause it -to be activated as the current one. +Use arrow keys to move left, right, up, and down among the cells. You may also +click the mouse on a cell to cause it to be activated as the current one. -Going beyond the borders of the window results in scrolling -the current view. It is not possible to go up from first row -or left from the first column; but it is possible to wrap back -to start from the last row and last column. +Note that it is not possible to move around the formula; the formula can only be +edited from its end by adding or removing characters. -2.6. Formula +Going beyond the borders of the window results in scrolling the current view. It +is not possible to go up from first row or left from the first column; but it is +possible to wrap back to start from the last row and last column. -The spreadsheet formulas operate on a stack. Operands of an -operation (e.g. plus) are first pushed to the stack and then -the operation is performed. If a formula on a cell produces -*exactly* one result then that is shown in the cell. Otherwise, -the formula is interpreted as a string and shown as it is. +#### 2.6. Formulas + +The spreadsheet formulas operate on a stack. Operands of an operation (e.g. +plus) are first pushed to the stack and then the operation is performed. If a +formula on a cell produces *exactly* one result then that is shown in the cell. +Otherwise, the formula is interpreted as a string and shown as it is. An example of a simple formula, simply specifying a number is - 123.50 +``` +123.50 +``` Another simple formula refers to a cell: - A1 +``` +A1 +``` -This particular example formula referred to the first cell of -the first row in the spreadsheet. Arithmetic operations require -both arguments: +This particular example formula referred to the first cell of the first row in +the spreadsheet. Arithmetic operations require both arguments: - A1 A2 + - B1 B2 * - C1 C2 - - D1 D2 / +``` +A1 A2 + +B1 B2 * +C1 C2 - +D1 D2 / +``` -More complex formulae can be constructed by combining these -simple ones: +More complex formulae can be constructed by combining these simple ones: - A1 A2 + 2 * +``` +A1 A2 + 2 * +``` -This example calculated the sum of the cells A1 and A2, and then -multiplied the result by two. +This example calculates the sum of the cells `A1` and `A2`, and then multiplies +the result by two. -The currently selected cell is always in a state where it can -be edited. Press any key to add a character at the end of the -formula; press BackSpace to delete the last one. Any resulting -recalculations are immediately visible. [Note how much nicer -this feature is as you get used to it, compared to the behaviour -of certain commercial spreadsheet programs.] +The currently selected cell is always in a state where it can be edited. Press +any key to add a character at the end of the formula; press backspace to delete +the last character. Any resulting recalculations are immediately visible. (Note +how much nicer this feature is as you get used to it, compared to the behaviour +of certain commercial spreadsheet programs.) -2.7. Graphical Formulas +#### 2.7. Graphical Formulas -The program supports two types of graphical representations of the -data in the cells: pie charts and histograms. The pie chart can -consist of any number of slices, and is constructed by putting -the pie amounts in stack and using the @ operator. The program -automatically computes the relative size of the slices. +The program supports two types of graphical representations of the data in the +cells: pie charts and histograms. The pie chart can consist of any number of +slices, and is constructed by putting the pie amounts in stack and using the `@` +operator. The program automatically computes the relative size of the slices. - A1 A2 A3 A4 @ +``` +A1 A2 A3 A4 @ +``` -This example would draw a pie slice of four cells, A1 to A4. +This example would draw a pie chart of four cells, `A1` to `A4`. The pie formula is shown above the pie for reference. -The histograms are drawn in a similar manner, by using the ! -operator: +The histograms are drawn in a similar manner, by using the `!` operator: - A1 A2 A3 A3 ! +``` +A1 A2 A3 A3 ! +``` -2.8. Errors in Formulas +#### 2.8. Errors in Formulas -The program detects recursive reference attempts, references -cells not containing a numerical value, attempts to define -formulas with zero, two, or more results remaining in the stack, -and syntax errors of formulas. Note that typically as the user -types in a formula, it toggles between valid and invalid forms -dynamically as all single character changes are immediately -taken in account. This is not dangerous, just complete the -formula and view the results. +The program detects recursive reference attempts, references cells not +containing a numerical value, attempts to define formulas with zero, two, or +more results remaining on the stack, and syntax errors of formulas. Note that +typically as the user types in a formula, it toggles between valid and invalid +forms dynamically as all single character changes are immediately taken in +account. This is not dangerous, just complete the formula and view the results. -Errors are signalled by showing the formula on a cell instead -of the numerical value supposedly returned by it. +Errors are signalled by showing the formula on a cell instead of the numerical +value supposedly returned by it. Division by zero results in an IEEE Inf number. -2.9. Compilation Parameters and Configuration +#### 2.9. Compilation Parameters and Configuration This section explains the meaning and rationale for the compile time parameters: +--- + +``` -DC=XK_Up -DL=XK_Down -DO=XK_Left -DV=XK_Right -DR=XK_Escape -D_=XK_BackSpace +``` -These definitions can be used to change the user interface -of the program with respect to special keys. The four first -ones define the movement operations and the latter two ones -define the program termination and character deletion keys. -Typical modifications to these parameters include changing -character deletion to the key the user is most familiar with, -which could also be XK_Delete. XK_Escape might be better -in some cases as one of the function keys. Likewise for the -cursor keys. +These definitions can be used to change the user interface of the program with +respect to special keys. The four first ones define the movement operations and +the latter two ones define the program termination and character deletion keys. +Typical modifications to these parameters include changing character deletion to +the key the user is most familiar with, which could also be `XK_Delete`. +`XK_Escape` might be better in some cases as one of the function keys. Likewise +for the arrow keys. +--- +``` -DU=40 +``` -This parameter defines the maximum dimensions of the stored -and handled spreadsheet (but see section 4.4 for a warning -about changing this without thinking about the consequences!). +This parameter defines the maximum dimensions of the stored and handled +spreadsheet (but see section 4.4 for a warning about changing this without +thinking about the consequences!). +--- +``` -DT=98 +``` -This parameter defines the maximum length of a formula in one -cell. Note the warning in 4.4. +This parameter defines the maximum length of a formula in one cell. Note the +warning in section 4.4. +--- +``` -Dz="(T+1)*U*U" +``` -Defines the number of bytes in a spreadsheet file. The number is -automatically adjusted when the spreadsheet size parameters are -changed. Note the warning in 4.4. +Defines the number of bytes in a spreadsheet file. The number is automatically +adjusted when the spreadsheet size parameters are changed. Note the warning in +section 4.4. +--- +``` -DQ=80 -DS=20 +``` -These two parameters define the visual dimensions of a cell. -Changing these may be necessary on your system if the default -font sizes differ from those in the systems we've tested the -program with. S also defines the size of the left (x1) and top -margins (x2). +These two parameters define the visual dimensions of a cell. Changing these may +be necessary on your system if the default font sizes differ from those in the +systems we've tested the program with. `S` also defines the size of the left +(`x1`) and top margins (`x2`). +--- +``` -DN=10 +``` -This is the x-indentation of text inside a cell. Changing -this may be necessary to suit other font sizes and -different X environments. +This is the x-indentation of text inside a cell. Changing this may be necessary +to suit other font sizes and different X environments. +--- +``` -DB=5 +``` -This is the y-indentation of text inside a cell. Changing -this may be necessary to suit other font sizes and -different X environments. +This is the y-indentation of text inside a cell. Changing this may be necessary +to suit other font sizes and different X environments. +--- +``` -DG=23 +``` -This parameter is the number of cell rows visible at one +This parameter is the number of cell rows visible at one time. + +--- + +``` +-Dp=7 +``` + +This parameter is one smaller than the number of cells columns visible at one time. - --Dp=7 - -This parameter is one smaller than the number of cells columns -visible at one time. +--- +``` -DM="((p+1)*Q)+S" -DH="(G*S)+S+S" +``` -These parameters are the window x and y sizes of the spreadsheet -program window. With these definitions, they are automatically -reflecting the at-one-time-visible cell row/column amounts. -Hence, we recommend changing the G and p parameters if you want -to change the window size in normal cases. Experimentation with -M and H can be used to get other types of effect such as adding -a margin also at the bottom of the window. +These parameters are the window x and y sizes of the spreadsheet program window. +With these definitions, they are automatically reflecting the +at-one-time-visible cell row/column amounts. Hence, we recommend changing the +`G` and `p` parameters if you want to change the window size in normal cases. +Experimentation with `M` and `H` can be used to get other types of effect such +as adding a margin also at the bottom of the window. -3. IMPLEMENTATION +--- -It's better to just read the code. But note the use of -stack in the implementation of @ and ! operators, and note -the use of *#i in one of the macros [can you see why?]. -Extreme compression has been the key in writing this -program. With compression have come the use of ASCII code -numbers instead of character constants and so on. [This -particular obfuscation is not really a desirable one as -it is not completely portable. But it certainly was a -necessary one.] +### 3. IMPLEMENTATION -What does or does not "i(=)" do and why? +It's better to just read the code. But note the use of stack in the +implementation of `@` and `!` operators, and note the use of `*#i` in one of the +macros (can you see why?). Extreme compression has been the key in writing this +program. With compression have come the use of ASCII code numbers instead of +character constants and so on. (This particular obfuscation is not really a +desirable one as it is not completely portable. But it certainly was a necessary +one.) -4. WARNINGS AND CAVEATS +What does `i(=)` do or does it do anything? Why? -4.1. X11 Paths in Compilation +### 4. WARNINGS AND CAVEATS -The given build file may have to be edited to insert correct -library and include file path names. +#### 4.1. X11 Paths in Compilation -4.2. Font Sizes +The given Makefile may have to be edited to insert correct library and include +file path names. -We've tested the program with limited amount of X servers. -It is possible that other systems use default font sizes or -other parameters that cause the visual looks to be different -or perhaps even unusable; if this happens, changing compile-time -parameters explained in section 2.8 may help. +#### 4.2. Font Sizes -4.3. Screen Sizes +We've tested the program with limited amount of X servers. It is possible that +other systems use default font sizes or other parameters that cause the visual +looks to be different or perhaps even unusable; if this happens, changing +compile-time parameters explained in section 2.8 might help. -The size of the window as it comes up - a parameter as defined -in compile-time - has been set suitable for a small laptop screen. -Larger screens may benefit from setting these parameters higher. -Smaller screens require changing the parameters so that all of the -window becomes visible. +#### 4.3. Screen Sizes -4.4. Spreadsheet Dimension Changes +The size of the window as it comes up - a parameter as defined in compile-time - +has been set suitable for a small laptop screen. Larger screens may benefit +from setting these parameters higher. Smaller screens require changing the +parameters so that all of the window becomes visible. -The size of the read, manipulated, and stored spreadsheets is -defined by a compile time parameter. However, changing this -parameter is not entirely trivial. The following constraints -apply: +#### 4.4. Spreadsheet Dimension Changes -(a) Horizontal (alphabet) dimension handling will always be -A to Z regardless of the actual allocated memory area. +The size of the read, manipulated, and stored spreadsheets is defined by a +compile time parameter. However, changing this parameter is not entirely +trivial. The following constraints apply: -(b) Any change in the dimension parameter renders existing -spreadsheet files unsuitable. +- Horizontal (alphabet) dimension handling will always be A to Z regardless of +the actual allocated memory area. -4.5. ASCII Reliance +- Any change in the dimension parameter renders existing spreadsheet files +unusable. -The software relies on running on ASCII-based code system. -Why? Because "32" is shorter than "' '". +#### 4.5. ASCII Reliance -4.6. Command Line Single Character Defines +The software relies on running on ASCII-based code system. Why? Because `32` is +shorter than `' '`. -The use of single character (e.g. G or p) for a -D option -may break certain systems, if those characters are used -in the included X header files in certain kinds of places. -If this happens, you may move the offending character to -a new name by exchanging it on the command line and in -the program with another character. Note that there are -*no* free characters in the program currently. +#### 4.6. Command Line Single Character Defines + +The use of single character (e.g. `G` or `p`) for a -D option might break +certain systems, if those characters are used in the included X header files in +certain kinds of places. If this happens, you may move the offending character +to a new name by exchanging it on the command line and in the program with +another character. Note that there are *no* free characters in the program +currently. ## Copyright and CC BY-SA 4.0 License: diff --git a/2000/jarijyrki/sheet1.info b/2000/jarijyrki/finance.sheet similarity index 100% rename from 2000/jarijyrki/sheet1.info rename to 2000/jarijyrki/finance.sheet diff --git a/2000/natori/.gitignore b/2000/natori/.gitignore index c2f12625e..3a5d1f9c4 100644 --- a/2000/natori/.gitignore +++ b/2000/natori/.gitignore @@ -1 +1,2 @@ natori +natori.alt diff --git a/2000/natori/Makefile b/2000/natori/Makefile index 5f99c6a47..c2709255c 100644 --- a/2000/natori/Makefile +++ b/2000/natori/Makefile @@ -113,8 +113,8 @@ OBJ= ${PROG}.o DATA= TARGET= ${PROG} # -ALT_OBJ= -ALT_TARGET= +ALT_OBJ= ${PROG}.alt.o +ALT_TARGET= ${PROG}.alt ################# diff --git a/2000/natori/README.md b/2000/natori/README.md index 94bae75e3..ca67af85f 100644 --- a/2000/natori/README.md +++ b/2000/natori/README.md @@ -29,6 +29,20 @@ compile at all (gcc and clang respectively). Thank you Cody for your assistance! echo "Do or do not. There is no try." ``` +### Alternate code: + +The author noted that those in the southern hemisphere might want to change +`acos(l/2)` into `acos(-l/2)`. Cody went ahead and made an alt version to do +this. + +To run: + +```sh +make alt +``` + +Use `natori.alt` as you would `natori`. + ## Judges' remarks: Here is a nice compact program that changes with the phase of the moon. @@ -46,8 +60,8 @@ This program outputs a rough image of the moon in its current phase. The main obfuscation of this entry is its complicated double recursion (without any loop or conditional statement). -People living in the southern hemisphere may want to change acos(l/2) -into acos(-l/2). +People living in the southern hemisphere may want to change `acos(l/2)` +into `acos(-l/2)`. ## Copyright and CC BY-SA 4.0 License: diff --git a/2000/natori/natori.alt.c b/2000/natori/natori.alt.c new file mode 100644 index 000000000..ce74329cd --- /dev/null +++ b/2000/natori/natori.alt.c @@ -0,0 +1,4 @@ +double l; +int moon(int _, int o, int O){ +return putchar((_--+22&&_+44&&main(_,-43,_),_&&(int)o)?(main(-43,(int)++o,(int)O),((l=((int)o+21)/sqrt(3-(int)O*22-(int)O*(int)O),l*l<4&&(fabs(((time(0)-607728)%2551443)/405859.-4.7+acos(-l/2))<1.57))[" #"])):10);} +main(int _,char**o,char**O){return moon(_, (int)o, (int)O); } diff --git a/2000/primenum/README.md b/2000/primenum/README.md index ef2cd25fa..4b711a1dc 100644 --- a/2000/primenum/README.md +++ b/2000/primenum/README.md @@ -1,8 +1,6 @@ # Best Abuse of CPP -Raymond Cheong -[address subject to change] -MD, USA +Raymond Cheong ## To build: @@ -18,7 +16,15 @@ echo n | ./primenum n ``` -NOTE: n is an integer. +NOTE: `n` is an integer. + +### INABIAF - it's not a bug it's a feature! :-) + +Although the name of the program suggests it prints prime numbers this is not +the case. This is by design. See the author's comments for more details or +better yet look at the code and if necessary try it out. + +A crash in the program is known as well. This is also a feature. ## Try: @@ -49,16 +55,18 @@ numbers up to a given number (as specified on the command line). But novice programmers especially know that mistakes are often made in translating pseudocode to real code, often resulting in programs with unexpected and confusing output. Clearly, the program contains several -syntax "mistakes" (e.g. LessThanOrEqualTo) and blatant "errors" (e.g. -Zero). This program clearly requires "debugging." +syntax "mistakes" (e.g. `LessThanOrEqualTo`) and blatant "errors" (e.g. +`Zero`). This program clearly requires "debugging." As a result of these "bugs", the program does not calculate primes at all. Instead, the program reads input from stdin and returns garbled text on stdout. Fortunately, you can recover the original message simply by running the program a second time. Try: - ./primenum n < textfile | ./primenum n > textfile2 - diff textfile textfile2 +```sh +./primenum n < textfile | ./primenum n > textfile2 +diff textfile textfile2 +``` where n is the same number (modulo 64). So, the prime number generator is actually a simple text encoder/decoder! Of course, don't forget that @@ -67,22 +75,28 @@ argument, otherwise the "bugs" in the program will cause it to crash! ### Features - The program attempts to mislead the reader into thinking that it - generates prime numbers. It does this by - * describing a correct algorithm in pseudocode, - * using partially correct conversion of pseudocode to real code, - * using suggestive variable names, and + generates prime numbers. It does this by: + * describing a correct algorithm in pseudocode; + * using partially correct conversion of pseudocode to real code; + * using suggestive variable names; and * using a suggestive program name. + - The program demonstrates a novel method of abusing the C preprocessor. -- How the filter algorithm works is left as an exercise to the reader. + +- Determining how the filter algorithm works is left as an exercise to the + reader. + - OK, so running it through the preprocessor strips away the prime - number front. But ye be warned: not a11 variab1es1es are identica1 :-) + number front. But ye be warned: "not a11 variab1es1es are identica1" :-) + - Other features include * useless variables * useless if * a for loop that's used as an if statement * dependence on the high bit being 0 + - Try also - echo THIS MESSAGE IS IN ALL CAPS | ./primenum 32 + `echo THIS MESSAGE IS IN ALL CAPS | ./primenum 32` ## Copyright and CC BY-SA 4.0 License: diff --git a/2000/rince/README.md b/2000/rince/README.md index 0bf04272e..ee526d650 100644 --- a/2000/rince/README.md +++ b/2000/rince/README.md @@ -1,11 +1,11 @@ # Astronomically Obfuscated -James Bonfield -MRC Laboratory of Molcular Biology -Hills Road, -Cambridge -CB2 2QH -England +James Bonfield +MRC Laboratory of Molcular Biology +Hills Road +Cambridge +CB2 2QH +England ## To build: @@ -19,6 +19,11 @@ make ./rince number number2 ``` +### INABIAF - it's not a bug it's a feature! :-) + +If `DISPLAY` is not set the program will very likely crash or do something +different. + ## Try: ```sh @@ -28,11 +33,11 @@ make dmy2jd ## Judges' remarks: -This program may have you going around in circles :-) Try running it -first before reading the Selected Author's Comments below. +This program may have you going around in circles :-) Try running it first +before reading the author's remarks below. -The judges verified the correctness of output for recent dates -thru visual observation. +The judges verified the correctness of output for recent dates through visual +observation. ## Author's remarks: @@ -60,32 +65,37 @@ the fraction of a day to skip forward for each screen refresh. I suggest: To display the output (still guessing?) for a given date, specify two arguments. The first argument is as before and the second argument is a -Julian day number (given as a fractional component). Eg: +Julian day number (given as a fractional component). E.g.: ```sh ./rince 0 2441193.6 ./rince 0.01 2441193.6 ``` -A Julian day is defined to be the number of days since January 1st in -the year -4712 (4713BC), starting at 12 noon GMT.[1] To aid conversion -from our time (GMT) to Julian day there is a supplementary program -named: dmy2jd.c. Run it with "day_float month year" as arguments. See -below for an example. +A Julian day is defined to be the number of days since January 1st in the year +`-4712 (4713BC)`, starting at 12 noon GMT.\[1\] To aid conversion from our time +(GMT) to Julian day there is a supplementary program named: +[dmy2jd.c](dmy2jd.c). Run it with `day_float month year` as arguments. See below +for an example. ### What it does -This program plots the positions of the four Galilean moons of Jupiter, -as seen from earth. It doesn't correct for your location on earth, but I -assure you that the parallax is minimal! +This program plots the positions of the four [Galilean +moons](https://en.wikipedia.org/wiki/Galilean_moons) of +[Jupiter](https://en.wikipedia.org/wiki/Jupiter), as seen from +[Earth](https://en.wikipedia.org/wiki/Earth). It doesn't correct for your +location on Earth, but I assure you that the +[parallax](https://en.wikipedia.org/wiki/Parallax#Astronomy) is minimal! -The moons are labelled with roman numerals from I to IV. I being the +The moons are labelled with Roman numerals from I to IV. I being the closest to the planet and IV being the furthest. They are: +``` I Io II Europa III Ganymede IV Callisto +``` Amazingly, all it takes is a pair of binoculars to see the Galilean moons, so the results can be experimentally checked. (Note that at present, the @@ -95,8 +105,9 @@ The positions of the moons should be correct for binoculars, but possibly not if you have a telescope or if you are in the southern hemisphere. In that case I suggest that to get the correct image you look at the screen from inside the monitor whilst standing on your head. In case of -confusion, please consult the following chart (*): +confusion, please consult the following chart (\*): +``` N ^ | @@ -104,14 +115,15 @@ confusion, please consult the following chart (*): | v S +``` -(*) Not to scale. +(\*) Not to scale. ### History Galileo discovered the moons in January 1610. -"http://www-isds.jpl.nasa.gov/cwo/cwo_54ga/html/cd/galileo.htm" states -the following: + +states the following: ``` By early 1610, Galileo had further improved his telescope by @@ -157,47 +169,59 @@ Thus we can plot Galileo's discoveries using the following three plots: ``` However we can go one better by seeing what Galileo would have seen if it -wasn't cloudy on the 9th. Try "./rince 0 `./dmy2jd 9.85 1 1610`" to see -what he was missing out on. I wonder what he'd have made of that! +wasn't cloudy on the 9th. Try: + + +```sh +./rince 0 `./dmy2jd 9.85 1 1610` +``` + +to see what he was missing out on. I wonder what he'd have made of that! Galileo discovered the fourth moon a few days later. I've tried typing these dates in to two Java based Jovian moon plotters, but both I tried had problems dealing with dates earlier than 1900. More -professional software, such as the SkyMap program [3] gets these values +professional software, such as the +[SkyMap](http://www.bmsoftware.com/skymappro9.htm) gets these values correct and this compares well with the above description and with this IOCCC entry. - -The year 4713BC was chosen by Joseph Justus Scaliger in the 16th Century, -so clearly this program has a long history :-) A more complete description -of the origins of Julian Days can be found at: - -http://aa.usno.navy.mil/AA/faq/docs/millennium.html +The year 4713BC was chosen by [Joseph Justus +Scaliger](https://en.wikipedia.org/wiki/Joseph_Justus_Scaliger) in the 16th +Century, so clearly this program has a long history :-) A more complete +description of the origins of Julian Days can be found at +. ### Assumptions +This program assumes: + 1. The ASCII character set is used. 2. That an enormous comet hasn't changed the course of Jupiter (or Earth!). -3. That the date has not been specified as the gap between the Julian and Gregorian calendar. +3. That the date has not been specified as the gap between the +[Julian](https://en.wikipedia.org/wiki/Julian_calendar) and +[Gregorian](https://en.wikipedia.org/wiki/Gregorian_calendar) calendar. -4. That the DISPLAY environment variable is set and the X display can opened. If this is not the case the program will crash. +4. That the `DISPLAY` environment variable is set and the X display can opened. +If this is not the case the program will crash. 5. There is a year 2000BC problem :-) -More specifically, the plots for dates that far back are too inaccurate -to be of realistic use. Comparisons against SkyMap Pro [3] show that -there is a good similarity (but not much more) up to about 500BC. + More specifically, the plots for dates that far back are too inaccurate to + be of realistic use. Comparisons against [SkyMap + Pro](http://www.bmsoftware.com/skymappro9.htm) show that there is a good + similarity (but not much more) up to about 500BC. 6. The code definitely is not portable - it will produce incorrect results if run from the surface of Mars. ### Obfuscations -In addition to the normal obfuscations, I feel that the code contains -some less common tricks. Taken through the standard rounds listed in the -guidelines, the code attempts to pass these as follows: +In addition to the normal obfuscations, I feel that the code contains some less +common tricks. Taken through the standard rounds listed in the +[guidelines](/2000/guidelines.txt), the code attempts to pass these as follows: 1. Look at the original source @@ -210,26 +234,26 @@ guidelines, the code attempts to pass these as follows: large string constant could not be split up using a "partA" "partB" method which clearly limits the code layout. However the space saved by using a single long string constant is more than - outweighed by ability to further obfuscate. + outweighed by the ability to further obfuscate. 2. convert ANSI tri-graphs to ASCII These are not used. -3. C pre-process the source ignoring #include lines -4. C pre-process the source ignoring #define and #include lines +3. C pre-process the source ignoring `#include` lines +4. C pre-process the source ignoring `#define` and `#include` lines This does a good job of expanding out the code, but it does not - clarify things greatly. The use of #defines has been restricted + clarify things greatly. The use of `#defines` has been restricted primarily to a space-saving mechanism. - Additionally, the use of typedefs means that the types used are + Additionally, the use of `typedef`s means that the types used are still obscured unless further replacement edits are made. 5. Run it through a C beautifier. GNU indent seems to do a reasonable job, provided that the - #defines are expanded first. This doesn't lay the algorithm + `#define`s are expanded first. This doesn't lay the algorithm particularly bare though as most of the obfuscations are not simple code layouts. @@ -237,15 +261,14 @@ guidelines, the code attempts to pass these as follows: The algorithm operates on two levels. The main visible level is by taking a large string and breaking this down into a series of - op-codes (which I have termed J-code). These are then executed. + opcodes (which I have termed J-code). These are then executed. To get to the real method of how it works, you need to decode - the op-code string (which deliberately contains as many ; { and - } symbols as possible), which will give you a reverse-polish + the opcode string (which deliberately contains as many `;`, `{` and + `}` symbols as possible), which will give you a reverse-polish notation chunk of mathematics. - Sensible people amongst you will simply refer to the referenced - book :-) + Sensible people amongst you will simply refer to the referenced book :-) 7. Lint it. @@ -260,69 +283,63 @@ guidelines, the code attempts to pass these as follows: I'm sorry to say that there are several warnings issued by the compiler. - Firstly, the return type for X() is not specified, so it - defaults to int. Horror of all horrors - this function does not - return an integer type (it doesn't contain any specific - returns). The return value from X() is not accessed. The same - problem occurs in main - it does not return. However main never - exits unless there is a serious error. + Firstly, the return type for `X()` is not specified, so it defaults to int. + Horror of all horrors - this function does not return an integer type (it + doesn't contain any specific returns). The return value from `X()` is not + accessed. The same problem occurs in `main()` - it does not return. However + `main()` never exits unless there is a serious error. - The 6th argument of XDrawText (which should be XTextItem) is + The 6th argument of `XDrawText` (which should be `XTextItem`) is passed as a compatible structure, but without casting. This is to reduce code space. A more elegant solution is to remove the - "struct {...} Z" completely and use "XTextItem - f={i-127+r/3*2,r%3+r/3+1,0,E}" at the start of XDrawText + `struct {...} Z` completely and use `XTextItem + f={i-127+r/3*2,r%3+r/3+1,0,E}` at the start of `XDrawText` block. Although this is accepted by several compilers, it is not strict ANSI due to the non-constant initialisers. A pity. - Note that I make use of usleep(). This is a POSIX call (it is - BSD), but it supported on many systems. It may be implemented - using select() or poll() if required, or as a final solution you - may change the usleep(10000) to sleep(1). To compile on systems - which do not have usleep, but do have select, the following may - suffice as an additional compiler argument: + Note that I make use of `usleep()`. This is a POSIX call (it is BSD), but it's + supported on many systems. It may be implemented using `select()` or `poll()` if + required, or as a final solution you can change the `usleep(10000)` to + `sleep(1)`. To compile on systems which do not have `usleep()`, but do have + `select()`, the following may suffice as an additional compiler argument: -```sh --Dusleep={time_t v[2]={0,10000};select(0,0,0,0,v);} -``` + ``` + -Dusleep={time_t v[2]={0,10000};select(0,0,0,0,v);} + ``` - Gcc complains about "unreachable code at beginning of switch + gcc complains about "unreachable code at beginning of switch statement", although removing some of this code will prevent the algorithm from working. - Gcc also suggests that I should be using extra parenthesis, but + gcc also suggests that I should be using extra parenthesis, but I'm taking this as good comment :-) - In addition to the above, the program has the following useful(?) obfuscations: -1. The algorithm requires many floating point numbers (about - 50). These are encoded as ASCII. +1. The algorithm requires many floating point numbers (about 50). These are +encoded as ASCII. -2. The J-code algorithm has op-codes designed to be space - saving. They are all one byte, but many are also considered as - white-space by the rules. This algorithm forms part of the same - string that the floating point constants are embedded - within. What does the ";" command do in J-code? +2. The J-code algorithm has opcodes designed to be space saving. They are all +one byte, but many are also considered as whitespace by the rules. This +algorithm forms part of the same string that the floating point constants are +embedded within. What does the `;` command do in J-code? -3. The J-code language is both stack based and variable based. This - "uncleanliness" is not ideal from a computer science angle, but - when has cleanliness been considered as good in IOCCC? :-) +3. The J-code language is both stack based and variable based. This +"uncleanliness" is not ideal from a computer science angle, but when has +cleanliness been considered as good in IOCCC? :-) -4. Association of unconnected data by implied function usage. Eg - use of strlen() and sizeof() simply to return useful numerical - values, using irrelevant arguments. +4. Association of unconnected data by implied function usage. E.g. use of +`strlen()` and `sizeof()` simply to return useful numerical values, using +irrelevant arguments. -5. As we already have a dependency on ASCII this has been abused - further. Specifically some integer constants are specified as - ASCII and some ASCII constants are integers. This hides the true - meaning for the values. +5. As we already have a dependency on ASCII this has been abused further. +Specifically some integer constants are specified as ASCII and some ASCII +constants are integers. This hides the true meaning for the values. -6. Red herrings: there's a couple of pieces of code whose - appearance is just there to mislead the unfirm of mind. - I've only tried to include such examples in places where at - first glance the code appears to be executed. +6. Red herrings: there are a couple of pieces of code whose appearance is just +there to mislead the infirm of mind. I've only tried to include such examples +in places where at first glance the code appears to be executed. ### References @@ -332,9 +349,6 @@ Jean Meeus. Published by Willmann-Bell Inc. [2] Astronomical algorithms (1st ed): pages 285-299. Jean Meeus. Published by Willmann-Bell Inc. -[3] Skymap Pro, by Chris Marriott -http://www.skymap.com/ - ## Copyright and CC BY-SA 4.0 License: This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved. diff --git a/2000/robison/README.md b/2000/robison/README.md index c57d7f3ea..21dd02f5d 100644 --- a/2000/robison/README.md +++ b/2000/robison/README.md @@ -1,9 +1,9 @@ # Best game -Arch D. Robison -1406 Country Lake Drive -Champaign IL 61821 -USA +Arch D. Robison +1406 Country Lake Drive +Champaign IL 61821 +US ## To build: @@ -42,17 +42,20 @@ Highly Compressed Program for Playing Hygienic Checkers ### FIELD OF INVENTION -The present invention generally relates to checkers. +The present invention generally relates to +[checkers](https://en.wikipedia.org/wiki/Checkers). ### BACKGROUND OF THE INVENTION -Within the field of checkers, the problem of finding a hygienic opponent -is difficult, as good opponents are peculiar to the tavern habitat of -cracker-barrels, pot-belly stoves, tobacco, and spittoons. +Within the field of [checkers](https://en.wikipedia.org/wiki/Checkers), the +problem of finding a hygienic opponent is difficult, as good opponents are +peculiar to the tavern habitat of cracker-barrels, pot-belly stoves, tobacco, +and spittoons. ### BRIEF SUMMARY OF THE INVENTION -The present invention plays checkers without spitting. +The present invention plays [checkers](https://en.wikipedia.org/wiki/Checkers) +without spitting. ### BRIEF DESCRIPTION OF SEVERAL VIEWS OF THE INVENTION @@ -66,36 +69,34 @@ FIG. 4 shows a method in accordance with the present invention. ### DETAILED DESCRIPTION OF THE INVENTION -Operator plays Black (x); the program plays White (o). Said Black goes -first. On operators turn, said program requests a position and direction. -FIG. 1 shows the numbering of the squares. FIG. 2 shows the numbering of -directions. As per standard rules, if one or more jumps are possible, one - of the jumps must be taken in preference to other moves. Said operator -enters the numbers for the position and direction. If after jumping over a -piece, another jump is possible, and said piece did not become a king after -said jump, standard rules require that another jump be taken. In said case, -said program requests a direction only in which to continue jumping from the -present position. Kings are denoted by upper case. FIG 3. shows a sample -board. There is a black king (X) on square 30 and a red king (O) on square -2. The numbers on the right are the numbers of the rightmost square in each -row. +Operator plays Black (`x`); the program plays White (`o`). Said Black goes first. +On operator's turn, said program requests a position and direction. FIG. 1 shows +the numbering of the squares. FIG. 2 shows the numbering of directions. As per +standard rules, if one or more jumps are possible, one of the jumps must be +taken in preference to other moves. Said operator enters the numbers for the +position and direction. If after jumping over a piece, another jump is +possible, and said piece did not become a king after said jump, standard rules +require that another jump be taken. In said case, said program requests a +direction only in which to continue jumping from the present position. Kings +are denoted by upper case. FIG. 3 shows a sample board. There is a black king +(`X`) on square 30 and a red king (`O`) on square 2. The numbers on the right are +the numbers of the rightmost square in each row. A player loses if they cannot make a legal move. Said loss is trivially true if player loses all of his/her pieces. The present invention announces said loser. -FIG. 4 shows a C program in accordance with the present invention. Control -flow is straightforward: control enters routine ``main'', executes a -plurality of statements, and exits via return statement. FIG. 4 presumes -that type int is 32 bits and short is 16 bits, which are essential to the -preferred embodiment of the invention. FIG. 4 also presumes that the host -computer uses ASCII encoding for characters. It should be obvious that -practitioners skilled in the art of C programming can remove said -limitations. +FIG. 4 shows a C program in accordance with the present invention. Control flow +is straightforward: control enters routine `main()`, executes a plurality of +statements, and exits via `return` statement. FIG. 4 presumes that type `int` +is `32 bits` and `short` is `16 bits`, which are essential to the preferred +embodiment of the invention. FIG. 4 also presumes that the host computer uses +ASCII encoding for characters. It should be obvious that practitioners skilled +in the art of C programming can remove said limitations. -The disclosure here describes a particular embodiment of the present -invention, and other embodiments within the spirit of this disclosure -are possible, as well as consumption of spirits while playing. +The disclosure here describes a particular embodiment of the present invention, +and other embodiments within the spirit of this disclosure are possible, as well +as consumption of spirits while playing. ### CLAIMS @@ -104,9 +105,8 @@ I claim, by letters patently absurd: 1. A method for playing checkers on a computer-based system, where said method's source code fits into 1536 countable bytes of source code, where a byte is countable if - - (a) it is not whitespace and - (b) it is not a {, }, or ; immediately followed by whitespace. + * it is not whitespace and + * it is not a '`{`', '`}`', or '`;`' immediately followed by whitespace. 2. The method of claim 1, further comprising a method of alpha-beta pruning that exploits the zero-sum nature of the game to unify alpha @@ -120,24 +120,23 @@ I claim, by letters patently absurd: skeptical manager that this is the well-known technique of "linear programming". -5. The method of claim 1, where ~- and -~ replace the obvious arithmetic +5. The method of claim 1, where `~-` and `-~` replace the obvious arithmetic operations. 6. The method of claim 1, further comprising a method where - - (a) strings are encrypted in a manner suitable as C strings, and - (b) 7-bit ASCII characters with uniform distribution are maximally - packed subject to the restriction that - (c) each byte is not countable. + * strings are encrypted in a manner suitable as C strings, and + * 7-bit ASCII characters with uniform distribution are maximally packed + subject to the restriction that each byte is not countable 7. A method for a computer-based system that uses a single shared code sequence to either sum a plurality of bits in an N-bit word or reverses them, in lg(N) time, depending upon a parameter. -DRAWINGS +### DRAWINGS -FIG 1. +#### FIG 1. +``` +--+--+--+--+--+--+--+--+ |32| |31| |30| |29| | +--+--+--+--+--+--+--+--+ @@ -155,17 +154,21 @@ FIG 1. +--+--+--+--+--+--+--+--+ | | 4| | 3| | 2| | 1| +--+--+--+--+--+--+--+--+ +``` -FIG. 2. +#### FIG. 2. +``` 1 0 \ / . / \ 3 2 +``` -FIG. 3. +#### FIG. 3. +``` o o X . 29 o . . . 25 o . . o 21 @@ -174,8 +177,9 @@ FIG. 3. . . x . 9 x x . . 5 x x O x 1 +``` -FIG. 4 +#### FIG. 4 [See attached listing.] diff --git a/2000/schneiderwent/README.md b/2000/schneiderwent/README.md index 214c22869..53c172ea3 100644 --- a/2000/schneiderwent/README.md +++ b/2000/schneiderwent/README.md @@ -1,7 +1,7 @@ # Most Timely Output -Craig Schneiderwent -WI, USA +Craig Schneiderwent +WI, US ## To build: @@ -19,8 +19,11 @@ make ```sh ./schneiderwent schneiderwent.data +./schneiderwent ``` +What's the difference? + ## Judges' remarks: Very nice play by the rules and portable text obfuscation. @@ -35,46 +38,43 @@ keeping the program portable between different encodings This entry displays the current time to the console, for example: - it's just after ten 'til 6 in the evening +> it's just after ten 'til 6 in the evening FWIW, none of the compilers with which this entry was tested issued any warnings or errors in compiling the source for this entry. No doubt lint will complain about the goto statements. -The schneiderwent.data file consists of the values used by multiple -table lookups. This is simply good program design, separating -these values from the source code allows changing the behavior of -the application without recompiling. +The [schneiderwent.data](schneiderwent.data) file consists of the values used by +multiple table lookups. This is simply good program design, separating these +values from the source code allows changing the behavior of the application +without recompiling. -Having learned COBOL at an early age, the pthreads of my thought +Having learned COBOL at an early age, the `pthread`s of my thought processes tend to be translated into code in a verbose manner. Some -of the #defines in this entry's code are to mitigate this personal +of the `#define`s in this entry's code are to mitigate this personal deficiency. +### Obfuscation + Obfuscation in this entry consists of: -* printfing console messages stored as EBCDIC character values - this is not an -attempt at encryption, but rather at cross platform compatibility +* `printf()`ing console messages stored as EBCDIC character values - this is not +an attempt at encryption, but rather at cross platform compatibility. * ASCII character values are calculated from the EBCDIC in a particularly ugly -abuse of the '?' operator -* detection of whether to print the ASCII or EBCDIC values is done by taking the -remainder of dividing the character 'J' by 2 - the ASCII value of the character -is even, the EBCDIC value is odd - -* the messages to be printfed are determined via multiple table lookups and -bitmasked values - -* for minutes, the bit position turned on is multiplied by two to determine the -message to be printfed - -* for hours, the straight bit position is used - -* this entry mostly eschews function calls for the often overlooked -setjmp/longjmp combination - -* the trigraphs are not there as obfuscation nor are they there to annoy the +abuse of the '?' operator. +* Detection of whether to print the ASCII or EBCDIC values is done by taking the +remainder of dividing the character `'J'` by `2` - the ASCII value of the +character is even, the EBCDIC value is odd. +* The messages to be `printf`ed are determined via multiple table lookups and +bit-masked values. +* For minutes, the bit position turned on is multiplied by two to determine the +message to be `printf`ed. +* For hours, the straight bit position is used. +* This entry mostly eschews function calls for the often overlooked +setjmp/longjmp combination. +* The trigraphs are not there as obfuscation nor are they there to annoy the judges - it's just the easiest way to get around the absence of square brackets -in a normal 3270 environment +in a normal 3270 environment. ## Copyright and CC BY-SA 4.0 License: diff --git a/2000/thadgavin/Makefile b/2000/thadgavin/Makefile index a5d6dad2b..652f70d46 100644 --- a/2000/thadgavin/Makefile +++ b/2000/thadgavin/Makefile @@ -129,8 +129,12 @@ all: data ${TARGET} supernova deep_magic magic charon pluto ${PROG}: ${PROG}.c + @echo "WARNING: if you are sensitive to rapid movement you should probably avoid this entry." ${CC} ${CFLAGS} $< -o $@ ${LIBS} +${PROG}_sdl: ${PROG}.c + ${CC} ${CFLAGS} -DSDL `${SDL1_CONFIG} --cflags` $< -o $@ ${LIBS} `${SDL1_CONFIG} --libs` + # alternative executable # alt: data ${ALT_TARGET} diff --git a/2000/thadgavin/README.md b/2000/thadgavin/README.md index fe9580e6e..82f7dda1f 100644 --- a/2000/thadgavin/README.md +++ b/2000/thadgavin/README.md @@ -1,16 +1,16 @@ # Most Portable Output - Thaddaeus Frogley - Creature Labs - 164 Hornbeams, - Harlow, Essex, - UK - - Gavin Buttimore - Creature Labs - 9 Elizabeth Way, - Cambridge, - UK, CB4 1DE +Thaddaeus Frogley +Creature Labs +164 Hornbeams +Harlow, Essex +UK + +Gavin Buttimore +Creature Labs +9 Elizabeth Way +Cambridge +UK, CB4 1DE ## To build: @@ -18,12 +18,40 @@ make ``` +NOTE: the author suggested `-O6` but at least some gcc versions support no more +than level 3 which is what the Makefile has. + +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed the code and +added an appropriate make rule so that the SDL version works independent from +the curses version (using the same code). To use it: + + +```sh +make thadgavin_sdl +``` + +Use `thadgavin_sdl` as you would `thadgavin` below. + +Thank you Cody for your assistance! + +To see the craziness of the SDL fix (because of a design choice of the SDL1 +developers) see the log for commit dd0b26b5d6325e8b6fdef1232156c8bb8c66613f. Be +prepared for a surprise. + ## To run: ```sh ./thadgavin ``` +WARNING: if you are sensitive to rapid movement you should probably avoid +this entry, both the SDL version and the curses version. + +NOTE: in curses mode you might want to type `reset` after execution of this +program as the program does not call `endwin()`. Using `reset` will clear the +screen. + + ## Try: ```sh @@ -37,45 +65,49 @@ SDL graphic library is not present, and is quite good at that, but the colors used in graphic mode (16 bit depth) are unfortunately less than dazzling. We could not test this entry in DOS mode. -## Author's remarks: +## Authors' remarks: -To run under DOS: +### To run under DOS: - Compile using DJGPP as follows: +Compile using DJGPP as follows: - gcc thadgavin.c -o thadgavin.exe -Wall -lm -O6 -mpentium -fomit-frame-pointer --ffast-math +```sh +gcc thadgavin.c -o thadgavin.exe -Wall -lm -O6 -mpentium -fomit-frame-pointer -ffast-math +``` -To run under Windows, X-Windows or MacOS using the -Simple DirectMedia Layer: +### To run under Windows, X-Windows or MacOS using the Simple DirectMedia Layer: - For example: - - gcc -O6 -lpthread -g -o thadgavin thadgavin.c -lSDL -DSDL -lm +```sh +gcc -O6 -lpthread -g -o thadgavin thadgavin.c -lSDL -DSDL -lm +``` -In gcc you may get the following warning: +### Warnings - prog.c:46: warning: passing arg 2 of `SDL_SetColors' from incompatible - pointer type +In gcc you might get the following warning: + +``` +thadgavin.c.c:46: warning: passing arg 2 of `SDL_SetColors' from incompatible pointer type +``` In Microsoft Visual Studio you may get warnings as follows: - prog.c(46) : warning C4133: 'function' : incompatible types - from 'unsigned - char *' to 'struct SDL_Color *' - prog.c(63) : warning C4026: function declared with formal parameter list - prog.c(77) : warning C4244: '=' : conversion from 'double ' to 'unsigned - char ', possible loss of data +``` +thadgavin.c(46) : warning C4133: 'function' : incompatible types - from 'unsigned +char *' to 'struct SDL_Color *' +thadgavin.c(63) : warning C4026: function declared with formal parameter list +thadgavin.c(77) : warning C4244: '=' : conversion from 'double ' to 'unsigned +char ', possible loss of data +``` But don't worry, this is completely normal. Recommended dosage: - At least 3 minutes taken 3 times a day when tired. +At least 3 minutes taken 3 times a day when tired. - Do not exceed 3 times recommended dose. May cause - sickness, dizziness, nausea. +Do not exceed 3 times recommended dose. May cause sickness, dizziness, nausea. ## Copyright and CC BY-SA 4.0 License: diff --git a/2000/thadgavin/thadgavin.c b/2000/thadgavin/thadgavin.c index d8c9bac8a..eb6122df9 100644 --- a/2000/thadgavin/thadgavin.c +++ b/2000/thadgavin/thadgavin.c @@ -38,7 +38,7 @@ (v,X*Y,0xA0000 ); } else{ r.x.ax= 0x13; __dpmi_int( 0x10,&r); } } #elif defined(SDL) - #include "SDL/SDL.h" + #include SDL_Surface *s; void F(int i){ if (i){ SDL_SetColors( s,h,0,256); SDL_UpdateRect @@ -57,7 +57,7 @@ LINES &~1,Y=y ## To build: @@ -43,22 +42,21 @@ Polyglots have come and gone, but this was the first one we'd seen where one language *used* another to perform its tasks. An interesting approach. Admittedly, it's not all that obfuscated - but there's more to it than you might think, since you have to make sure that your -changes don't change the shell code or the makefile. +changes don't change the shell code or the Makefile. ## Author's remarks: ### Summary -This program works as a C source file, a Makefile and also as a -Shell (/bin/sh) script. But unlike some other multi-language prog- -rams, this one is NOT meant to print "Hello, world" in all 3 cases -(At least in the true sense ;-)). The C, make and shell code build -upon each other to create a C program (?) which when executed as a -shell script will compile itself through the C compiler using a -makefile! - Pretty useful, Eh?. +This program works as a C source file, a Makefile and also as a shell +(`/bin/sh`) script. But unlike some other multi-language programs, this one is +NOT meant to print "Hello, world" in all 3 cases (At least in the true sense +;-)). The C, make and shell code build upon each other to create a C program (?) +which when executed as a shell script will compile itself through the C compiler +using a Makefile! - Pretty useful, Eh? -Probably, this is the first entry ever to fully satisfy Rule #1 -("Your entry must be a complete program") in the strictest sense;-) +Probably, this is the first entry ever to fully satisfy Rule #1 ("Your entry +must be a complete program") in the strictest sense;-) ### Top 5 reasons (IMHO) why this code is an entry for IOCCC @@ -76,27 +74,25 @@ obfuscation should be in C and not elsewhere???. Mmmmm...). 3. Extending Argument #2... Obfuscation done in the C code (comments?) create obfuscated code for the other 2 languages. This opens new possibilities to be explored in depth in future -IOCCCs. +`IOCCC`s. 4. LOOKS like a Makefile, WORKS like a shell script and COMPILES like a C program. -5. Does something useful (See Notes #1, #2). +5. Does something useful (See Notes #1 and #2 below). ### Notes 1. The program could have been something other than the simple "Hello, world" program that it is. It is possible to do `#include "prog2.c"` in the place of -the main(), leaving the complexities of the C file elsewhere and making this -source still acceptable to "make" and "sh". The following modification to the -last few lines will compile the IOCCC's famous `mkentry.c`. +the `main()`, leaving the complexities of the C file elsewhere and making this +source still acceptable to `make` and `sh`. The following modification to the +last few lines will compile the IOCCC's famous [mkentry.c](mkentry.c). -```make -.PHONY: /* true clean */ -#undef true -#include "mkentry.c" -``` + .PHONY: /* true clean */ + #undef true + #include "mkentry.c" Ain't that useful? @@ -104,18 +100,18 @@ Ain't that useful? very interesting things like generating C code on execution by adding additional code in make/sh (open up a loop????). This opens the possibilities of generating & compiling some -[obfuscated?] C code. (Maybe should try this if this program +(obfuscated?) C code. (Maybe should try this if this program fails at IOCCC 2000) 3. Changing the `%:%.c` dependency to a `$(PROG):$(PROG).c` form can compile this program with some other `make`s (I got it to -work in Windows using nmake and Gnuwin32's sh ;-) +work in Windows using nmake and Gnuwin32's sh ;-) ) 4. Interesting things to do: try `./tomx.c clean`. This will do the same as `make clean` :-)). Also: `./tomx.c all` -5. Be careful about the Tabs in the source code. Removing them -or converting Tabs to spaces can be disastrous. +5. Be careful about the tabs in the source code. Removing them +or converting tabs to spaces can be disastrous. ## Copyright and CC BY-SA 4.0 License: diff --git a/2000/tomx/mkentry.c b/2000/tomx/mkentry.c new file mode 100644 index 000000000..5e5fe6f4e --- /dev/null +++ b/2000/tomx/mkentry.c @@ -0,0 +1,1273 @@ +/* $Id: mkentry.c,v 1.6 1999/01/27 23:19:37 chongo Exp $ */ +/* + * Copyright (c) Leonid A. Broukhis, Jeremy Horn, Landon Curt Noll and + * Peter Seebach, 1998. + * + * All Rights Reserved. Permission for personal, education or non-profit use + * is granted provided this this copyright and notice are included in its + * entirety and remains unaltered. All other uses must receive prior + * permission in writing from the contest judges. + */ +/* + * mkentry - make an International Obfuscated C Code Contest entry + * + * usage: + * mkentry -r remarks -b build -p prog.c -o ioccc.entry + * + * -r remarks file with remarks about the entry + * -b build file containing how prog.c should be built + * -p prog.c the obfuscated program source file + * -o ioccc.entry ioccc entry output file + * + * compile by: + * cc mkentry.c -o mkentry + */ +/* + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +/* + * WARNING: + * + * 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. + * + * FOR MORE INFORMATION: + * + * You may contact the judges by sending an email to the following address: + * + * questions@ioccc.org (not the address for submitting entries) + * + * Questions and comments about the contest are welcome. + * + * Entries must be sent to: + * + * entry@ioccc.org + * + * but be sure to follow the rules and read the guidelines first! + * + * The rules and the guidelines may (and often do) change from year to + * year. You should be sure you have the current rules and guidelines + * prior to submitting entries. To obtain them, visit the following URL: + * + * http://www.ioccc.org + * + * Because contest rules change from year to year, one should only use this + * program for the year that it was intended. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* logic */ +#ifndef TRUE +# define TRUE 1 +#endif /* TRUE */ +#ifndef FALSE +# define FALSE 0 +#endif /* FALSE */ +#define EOF_OK TRUE +#define EOF_NOT_OK FALSE + +/* global limits */ +#define RULE_YEAR 2000 /* NOTE: should match the current year */ +#define START_DATE "01Feb2000 00:00 UTC" /* first confirmation received */ +#define MAX_COL 79 /* max column a line should hit */ +#define MAX_BUILD_SIZE 256 /* max how to build size */ +#define MAX_PROGRAM_SIZE 3217 /* max program source size */ +#define MAX_PROGRAM_SIZE2 1536 /* max program source size not counting + whitespace and {}; not followed by + whitespace or EOF */ +#define MAX_TITLE_LEN 31 /* max chars in the title */ +#define MAX_ENTRY_LEN 1 /* max length in the entry input line */ +#define MAX_ENTRY 8 /* max number of entries per person per year */ +#define MAX_FILE_LEN 1024 /* max filename length for a info file */ + +/* where to send entries */ +#define ENTRY_ADDR "entry@ioccc.org" + +/* uuencode process - assumes ASCII */ +#define UUENCODE(c) ((c) ? encode_str[(int)(c)&0x3f] : '`') +#define UUENCODE_LEN 45 /* max uuencode chunk size */ +#define UUINFO_MODE 0444 /* mode of an info file's uuencode file */ +#define UUBUILD_MODE 0444 /* mode of the build file's uuencode file */ +#define UUBUILD_NAME "build" /* name for the build file's uuencode file */ +#define UUPROG_MODE 0444 /* mode of the program's uuencode file */ +#define UUPROG_NAME "prog.c" /* name for the program's uuencode file */ + +/* encode_str[(char)val] is the uuencoded character of val */ +char encode_str[] = "`!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"; + +/* global declarations */ +char *program; /* our name */ +long start_time; /* the startup time */ + +/* forward declarations */ +void parse_args(int argc, char **argv, char **rname, + char **bname, char **pname, char **oname); +void usage(int exitval); +FILE *open_remark(char *filename); +FILE *open_build(char *filename); +FILE *open_program(char *filename); +FILE *open_output(char *filename); +void output_entry(FILE *output, char *oname); +void output_remark(FILE *output, char *oname, FILE *remark, char *rname); +void output_author(FILE *output, char *oname); +void output_info(FILE *output, char *oname); +void output_build(FILE *output, char *oname, FILE *build, char *bname); +void output_program(FILE *output, char *oname, FILE *prog, char *pname); +void output_end(FILE *output, char *oname); +int get_line(char *buf, int siz, int maxcol); +void output_till_dot(FILE *output, char *oname, char *leader); +int col_len(char *string); +void check_io(FILE *stream, char *name, int eof_ok); +void uuencode(FILE *output, char *oname, FILE *infile, + char *iname, int umode, char *uname); + +int +main(argc, argv) + int argc; /* arg count */ + char **argv; /* the args */ +{ + FILE *remark=NULL; /* open remarks stream */ + FILE *build=NULL; /* open build file stream */ + FILE *prog=NULL; /* open program stream */ + FILE *output=NULL; /* open output stream */ + char *rname=NULL; /* file with remarks about the entry */ + char *bname=NULL; /* file containing how prog.c should be built */ + char *pname=NULL; /* the obfuscated program source file */ + char *oname=NULL; /* ioccc entry output file */ + struct tm *tm; /* startup time structure */ + + /* + * check on the year + */ + start_time = time((long *)0); + tm = gmtime(&start_time); + if (tm->tm_year != RULE_YEAR-1900 && + (tm->tm_year != RULE_YEAR-1900+1 || tm->tm_mon != 0)) { + fprintf(stderr, + "%s: WARNING: this program applies to %d, which may differ from %d\n\n", + argv[0], RULE_YEAR, 1900+tm->tm_year); + } + + /* + * parse the command line args + */ + parse_args(argc, argv, &rname, &bname, &pname, &oname); + + /* + * open/check the input and output files + * + * We open and truncate the output file first, in case it is the same + * as one of the input files. + */ + output = open_output(oname); + remark = open_remark(rname); + build = open_build(bname); + prog = open_program(pname); + if (output==NULL || remark==NULL || build==NULL || prog==NULL) { + exit(1); + } + + /* + * output each section + */ + output_entry(output, oname); + output_remark(output, oname, remark, rname); + output_author(output, oname); + output_info(output, oname); + output_build(output, oname, build, bname); + output_program(output, oname, prog, pname); + output_end(output, oname); + + /* + * flush the output + */ + if (fflush(output) == EOF) { + fprintf(stderr, "%s: flush error in %s: ", program, oname); + perror(""); + exit(2); + } + + /* + * final words + */ + printf("\nYour entry can be found in %s. You should check this file\n", + oname); + printf("correct any problems and verify that the uudecode utility will\n"); + printf("correctly decode your build file and program.\n\n"); + printf("This program has been provided as a guide for submitters. In\n"); + printf("cases where it conflicts with the rules, the rules shall apply.\n"); + printf("It is your responsibility to ensure that your entry conforms to\n"); + printf("the current rules.\n\n"); + printf("Email your entries to:\n"); + printf("\t%s\n\n", ENTRY_ADDR); + printf("Please use the following subject when you email your entry:\n"); + printf("\tioccc entry\n\n"); + /* all done */ + return 0; +} + +/* + * parse_args - parse the command line args + * + * usage: + * argc arg count + * argv the args + * rname file with remarks about the entry + * bname file containing how prog.c should be built + * pname the obfuscated program source file + * oname ioccc entry output file + * + * Given the command line args, this function parses them and sets the + * required name flags. This function will return only if the command + * line syntax is correct. + */ +void +parse_args(int argc, char **argv, char **rname, + char **bname, char **pname, char **oname) +{ + char *optarg; /* -flag option operand */ + int flagname; /* the name of the -flag */ + int i; + + /* + * Not everyone has getopt, so we must parse args by hand. + */ + program = argv[0]; + for (i=1; i < argc; ++i) { + + /* determine the flagname */ + if (argv[i][0] != '-') { + usage(1); + /*NOTREACHED*/ + } + flagname = (int)argv[i][1]; + + /* determine the flag's operand */ + if (flagname != '\0' && argv[i][2] != '\0') { + optarg = &argv[i][2]; + } else { + if (i+1 >= argc) { + usage(2); + /*NOTREACHED*/ + } else { + optarg = argv[++i]; + } + } + + /* save the flag's operand in the correct global variable */ + switch (flagname) { + case 'r': + *rname = optarg; + break; + case 'b': + *bname = optarg; + break; + case 'p': + *pname = optarg; + break; + case 'o': + *oname = optarg; + break; + default: + usage(3); + /*NOTREACHED*/ + } + } + + /* + * verify that we have all of the required flags + */ + if (*rname == NULL || *bname == NULL || *pname == NULL || *oname == NULL) { + usage(4); + /*NOTREACHED*/ + } + return; +} + +/* + * usage - print a usage message and exit + * + * usage: + * exitval exit with this value + * + * This function does not return. + */ +void +usage(int exitval) +{ + fprintf(stderr, + "usage: %s -r remarks -b build -p prog.c -o ioccc.entry\n\n", program); + fprintf(stderr, "\t-r remarks\tfile with remarks about the entry\n"); + fprintf(stderr, "\t-b build\tfile containing how prog.c should be built\n"); + fprintf(stderr, "\t-p prog.c\tthe obfuscated program source file\n"); + fprintf(stderr, "\t-o ioccc.entry\tioccc entry output file\n"); + exit(exitval); +} + +/* + * open_remark - open/check the remark file + * + * usage: + * filename remark filename + * + * The remark file should be indented by 4 spaces, and should not extend + * beyond column MAX_COL. These are not requirements, so we only warn. + * + * This function returns NULL on I/O or format error. + */ +FILE * +open_remark(char *filename) +{ + FILE *stream; /* the opened file stream */ + char buf[BUFSIZ+1]; /* input buffer */ + int toolong=0; /* number of lines that are too long */ + int non_indent=0; /* number of lines not indented by 4 spaces */ + + /* + * open the remark input file + */ + stream = fopen(filename, "r"); + if (stream == NULL) { + fprintf(stderr, "%s: cannot open remark file: %s: ", + program, filename); + perror(""); + return(NULL); + } + + /* + * look at each line + */ + while (fgets(buf, BUFSIZ, stream) != NULL) { + + /* count lines that do not start with 4 spaces */ + if (buf[0] != '\n' && strncmp(buf, " ", 4) != 0) { + ++non_indent; + } + + /* count long lines */ + if (col_len(buf) > MAX_COL) { + /* found a line that is too long */ + ++toolong; + } + } + + /* watch for I/O errors */ + check_io(stream, filename, EOF_OK); + + /* note long lines if needed */ + if (toolong > 0) { + fprintf(stderr, + "%s: WARNING: %d line(s) from %s extend beyond the 80th column\n", + program, toolong, filename); + fprintf(stderr, + "%s: This is ok, but it would be nice to avoid\n\n", + program); + } + + /* note non-indented lines, if needed */ + if (non_indent > 0) { + fprintf(stderr, + "%s: WARNING: %d line(s) from %s are not indented by 4 spaces\n", + program, non_indent, filename); + fprintf(stderr, + "%s: This is ok, but it would be nice to avoid\n\n", + program); + } + + /* return the open file */ + rewind(stream); + return(stream); +} + +/* + * open_build - open/check the build file + * + * usage: + * filename build filename + * + * The how to build file must not be longer than MAX_BUILD_SIZE bytes. + * + * This function returns NULL on I/O or size error. + */ +FILE * +open_build(char *filename) +{ + FILE *stream; /* the opened file stream */ + struct stat statbuf; /* the status of the open file */ + + /* + * open the how to build input file + */ + stream = fopen(filename, "r"); + if (stream == NULL) { + fprintf(stderr, "%s: cannot open how to build file: %s: ", + program, filename); + perror(""); + return(NULL); + } + + /* + * determine the size of the file + */ + if (fstat(fileno(stream), &statbuf) < 0) { + fprintf(stderr, "%s: cannot stat how to build file: %s: ", + program, filename); + perror(""); + return(NULL); + } + if (statbuf.st_size > MAX_BUILD_SIZE) { + fprintf(stderr, + "%s: FATAL: the how to build file: %s, is %ld bytes long\n", + program, filename, (long) statbuf.st_size); + fprintf(stderr, + "%s: it may not be longer than %d bytes\n", + program, MAX_BUILD_SIZE); + return(NULL); + } + + /* return the open file */ + return(stream); +} + +/* + * open_program - open/check the program source file + * + * usage: + * filename source filename + * + * The program source file must be <= 3217 bytes. The number of + * non-whitespace and }{; chars not followed by whitespace must + * be <= 1536 bytes. + * + * This function returns NULL on I/O or size error. + */ +FILE * +open_program(char *filename) +{ + FILE *stream; /* the opened file stream */ + struct stat statbuf; /* the status of the open file */ + int count; /* special count size */ + int c; /* the character read */ + + /* + * open the program source input file + */ + stream = fopen(filename, "r"); + if (stream == NULL) { + fprintf(stderr, "%s: cannot open program source file: %s: ", + program, filename); + perror(""); + exit(7); + } + + /* + * determine the size of the file + */ + if (fstat(fileno(stream), &statbuf) < 0) { + fprintf(stderr, "%s: cannot stat program source file: %s: ", + program, filename); + perror(""); + return(NULL); + } + if (statbuf.st_size > MAX_PROGRAM_SIZE) { + fprintf(stderr, + "%s: FATAL: the program source file: %s, is %ld bytes long\n", + program, filename, (long) statbuf.st_size); + fprintf(stderr, + "%s: it may not be longer than %d bytes\n", + program, MAX_PROGRAM_SIZE); + return(NULL); + } + + /* + * count the non-whitespace, non {}; followed by whitespace chars + */ + count = 0; + c = 0; + while ((c=fgetc(stream)) != EOF) { + /* look at non-whitespace */ + if (!isascii(c) || !isspace(c)) { + switch (c) { + case '{': /* count if not followed by EOF or whitespace */ + case '}': + case ';': + /* peek at next char */ + c = fgetc(stream); + if (c != EOF && isascii(c) && !isspace(c)) { + /* not followed by whitespace or EOF, count it */ + ungetc(c, stream); + ++count; + } + break; + default: + ++count; + break; + } + } + } + + /* watch for I/O errors */ + check_io(stream, filename, EOF_OK); + + /* look at the special size */ + if (count > MAX_PROGRAM_SIZE2) { + fprintf(stderr, + "%s: FATAL: the number of bytes that are non-whitespace, and\n", + program); + fprintf(stderr, + "%s: that are not '{', '}', ';' followed by whitespace\n", + program); + fprintf(stderr, + "%s: or EOF must be <= %d bytes\n", + program, MAX_PROGRAM_SIZE2); + fprintf(stderr, + "%s: in %s, %d bytes were found\n", + program, filename, count); + return(NULL); + } + + /* return the open file */ + rewind(stream); + return(stream); +} + +/* + * open_output - open/check the entry output file + * + * usage: + * filename output filename + * + * This function returns NULL on open error. + */ +FILE * +open_output(char *filename) +{ + FILE *stream; /* the opened file stream */ + + /* + * open the ioccc entry output file + */ + stream = fopen(filename, "w"); + if (stream == NULL) { + fprintf(stderr, "%s: cannot open ioccc entry file for output: %s: ", + program, filename); + perror(""); + exit(8); + } + + /* return the open file */ + return(stream); +} + +/* + * output_entry - output the ---entry--- section + * + * usage: + * output entry's output file stream + * oname name of the output file + * + * Read the needed information form stdin, and write the entry section. + */ +void +output_entry(FILE *output, char *oname) +{ + char title[MAX_TITLE_LEN+1+1]; /* the entry's title */ + char buf[MAX_COL+1+1]; /* I/O buffer */ + int entry=0; /* entry number */ + int ret; /* fields processed by fscanf */ + int ok_line=0; /* 0 => the line is not ok */ + char skip; /* input to skip */ + time_t epoch_sec; /* seconds since the epoch */ + char *p; + + /* + * write the start of the section + */ + fprintf(output, "---entry---\n"); + check_io(output, oname, EOF_NOT_OK); + + /* + * write the rule year + */ + fprintf(output, "rule:\t%d\n", RULE_YEAR); + check_io(output, oname, EOF_NOT_OK); + + /* determine if this is a fix */ + printf("Is this a fix, update or resubmission to a "); + printf("previous entry (enter y or n)? "); + while (get_line(buf, 1+1, 0) <= 0 || !(buf[0]=='y' || buf[0]=='n')) { + printf("\nplease answer y or n: "); + } + if (buf[0] == 'y') { + fprintf(output, "fix:\ty\n"); + check_io(output, oname, EOF_NOT_OK); + printf("\nBe sure that the title and entry number that you give\n"); + printf("are the same of as the entry you are replacing\n"); + } else { + fprintf(output, "fix:\tn\n"); + check_io(output, oname, EOF_NOT_OK); + } + + /* + * write the title + */ + printf("\nThe first character of your title should match [a-zA-Z0-9_=]\n"); + printf("The next 0 to %d characters should match [a-zA-Z0-9_=+-]\n\n", + MAX_TITLE_LEN-1); + printf("It is suggested, but not required, that the title should\n"); + printf("incorporate your username; in the\n"); + printf("case of multiple authors, consider using parts of the usernames\n"); + printf("of the authors.\n\n"); + printf("enter your title: "); + do { + /* prompt and read a line */ + if ((ok_line = get_line(title, MAX_TITLE_LEN+1, MAX_COL-9)) <= 0) { + printf("\ntitle is too long, please re-enter: "); + continue; + } + + /* verify the pattern, not everyone has regexp, so do it by hand */ + if (!isascii((int)title[0]) || + !(isalnum((int)title[0]) || title[0] == '_' || title[0] == '=')) { + printf("\ninvalid first character in the title\n\n"); + printf("enter your title: "); + ok_line = 0; + } else { + for (p=(&title[1]); *p != '\0' && *p != '\n'; ++p) { + if (!isascii((int)*p) || + !(isalnum((int)*p) || + *p == '_' || *p == '=' || *p == '+' || *p == '-')) { + printf("\ninvalid character in the title\n\n"); + printf("enter your title: "); + ok_line = 0; + } + } + } + } while (ok_line <= 0); + fprintf(output, "title:\t%s", title); + check_io(output, oname, EOF_NOT_OK); + + /* + * write the entry number + */ + printf("\nEach person may submit up to %d entries per year.\n\n", + MAX_ENTRY); + printf("enter an entry number from 0 to %d inclusive: ", MAX_ENTRY-1); + do { + /* get a valid input line */ + fflush(stdout); + ret = fscanf(stdin, "%d[\n]", &entry); + check_io(stdin, "stdin", EOF_NOT_OK); + /* skip over input until newline is found */ + do { + skip = fgetc(stdin); + check_io(stdin, "stdin", EOF_NOT_OK); + if (skip != '\n') { + /* bad text in input, invalidate entry number */ + entry = -1; + } + } while (skip != '\n'); + + /* check if we have a number, and if it is in range */ + if (ret != 1 || entry < 0 || entry > MAX_ENTRY-1) { + printf( + "\nThe entry number must be between 0 and %d inclusive\n\n", + MAX_ENTRY-1); + printf("enter the entry number: "); + } + } while (ret != 1 || entry < 0 || entry > MAX_ENTRY-1); + fprintf(output, "entry:\t%d\n", entry); + check_io(output, oname, EOF_NOT_OK); + + /* + * write the submission date + */ + /* returns a newline */ + epoch_sec = time(NULL); + fprintf(output, "date:\t%s", asctime(gmtime(&epoch_sec))); + check_io(output, oname, EOF_NOT_OK); + + /* + * write the OS/machine host information + */ + printf( + "\nEnter the machine(s) and OS(s) under which your entry was tested.\n"); + output_till_dot(output, oname, "host:"); +} + +/* + * output_remark - output the ---remark--- section + * + * usage: + * output entry's output file stream + * oname name of the output file + * remark stream to the file containing remark text + * rname name of the remark file + * + * Read the needed information form stdin, and write the entry section. + */ +void +output_remark(FILE *output, char *oname, FILE *remark, char *rname) +{ + char buf[BUFSIZ+1]; /* input/output buffer */ + + /* + * write the start of the section + */ + fprintf(output, "---remark---\n"); + check_io(output, oname, EOF_NOT_OK); + + /* + * copy the remark file to the section + */ + while (fgets(buf, BUFSIZ, remark) != NULL) { + fputs(buf, output); + check_io(output, oname, EOF_NOT_OK); + } + check_io(remark, rname, EOF_OK); + + /* be sure that the remark section ends with a newline */ + if (buf[strlen(buf)-1] != '\n') { + fputc('\n', output); + check_io(output, oname, EOF_NOT_OK); + } +} + +/* + * output_author - output the ---author--- section + * + * usage: + * output entry's output file stream + * oname name of the output file + * + * Read the needed information from stdin, and write the author section. + * If multiple authors exist, multiple author sections will be written. + */ +void +output_author(FILE *output, char *oname) +{ + char buf[MAX_COL+1+1]; /* I/O buffer */ + int more_auths; /* TRUE => more authors to note */ + int auth_cnt=0; /* number of authors processed */ + + /* + * prompt the user for the author section + */ + printf("\nEnter information about each author. If your entry is after\n"); + printf("%s and before the contest deadline, the judges\n", START_DATE); + printf("will attempt to email back a confirmation to the first author\n"); + + /* + * place author information for each author in an individual section + */ + do { + + /* write the start of the section */ + fprintf(output, "---author---\n"); + check_io(output, oname, EOF_NOT_OK); + + /* write the author */ + printf("\nAuthor #%d name: ", ++auth_cnt); + while (get_line(buf, MAX_COL+1, MAX_COL-9) <= 0) { + printf("\nname too long, please re-enter: "); + } + fprintf(output, "name:\t%s", buf); + check_io(output, oname, EOF_NOT_OK); + + /* write the organization */ + printf("\nEnter the School/Company/Organization of author #%d\n", + auth_cnt); + printf("\nAuthor #%d org: ", auth_cnt); + while (get_line(buf, MAX_COL+1, MAX_COL-9) <= 0) { + printf("\nline too long, please re-enter: "); + } + fprintf(output, "org:\t%s", buf); + check_io(output, oname, EOF_NOT_OK); + + /* write the address */ + printf( + "\nEnter the postal address for author #%d. Be sure to include\n", + auth_cnt); + printf("your country and do not include your name.\n"); + output_till_dot(output, oname, "addr:"); + + /* write the email address */ + printf( + "\nEnter the email address for author #%d. Use an address from\n", + auth_cnt); + printf( + "a registered domain or well known site. If you give several\n"); + printf("forms, list them one per line.\n"); + output_till_dot(output, oname, "email:"); + + /* write the home page URL */ + printf( + "\nEnter the fully qualified home page URL for author #%d\n", + auth_cnt); + printf("including the http: part or type none: "); + while (get_line(buf, MAX_COL+1, MAX_COL-9) <= 0 || + (strncmp(buf, "http://", sizeof("http://")-1) != 0 && + strcmp(buf, "none\n") != 0)) { + printf("\nURL too long, does not begin with http:// or\n"); + printf("is not the word none\n"); + } + fprintf(output, "url:\t%s", buf); + check_io(output, oname, EOF_NOT_OK); + + /* write the anonymous status */ + printf("\nShould author #%d remain anonymous (enter y or n)? ", + auth_cnt); + while (get_line(buf, 1+1, 0) <= 0 || !(buf[0]=='y' || buf[0]=='n')) { + printf("\nplease answer y or n: "); + } + fprintf(output, "anon:\t%s", buf); + check_io(output, oname, EOF_NOT_OK); + + /* determine if there is another author */ + printf("\nIs there another author (enter y or n)? "); + while (get_line(buf, 1+1, 0) <= 0 || !(buf[0]=='y' || buf[0]=='n')) { + printf("\nplease answer y or n: "); + } + if (buf[0] == 'y') { + more_auths = TRUE; + } else { + more_auths = FALSE; + } + } while (more_auths == TRUE); + return; +} + +/* + * output_info - output the ---info--- section(s) + * + * usage: + * output entry's output file stream + * oname name of the output file + * + * Read the needed information from stdin, and write the info section. + * If multiple info files exist, multiple info sections will be written. + */ +void +output_info(FILE *output, char *oname) +{ + char infoname[MAX_FILE_LEN+1]; /* filename buffer */ + char yorn[1+1]; /* y or n answer */ + char *uuname; /* name to uuencode as */ + FILE *infile; /* info file stream */ + + /* + * prompt the user for info information + */ + printf("\nInfo files should be used only to supplement your entry.\n"); + printf("For example, info files may provide sample input or detailed\n"); + printf("information about your entry. Because they are supplemental,\n"); + printf("the entry should not require them to exist.\n\n"); + + /* + * while there is another info file to save, uuencode it + */ + printf("Do you have a info file to include (enter y or n)? "); + while (get_line(yorn, 1+1, 0) <= 0 || !(yorn[0]=='y' || yorn[0]=='n')) { + printf("\nplease answer y or n: "); + } + while (yorn[0] == 'y') { + + /* read the filename */ + printf("\nEnter the info filename: "); + while (get_line(infoname, MAX_FILE_LEN+1, 0) <= 0) { + printf("\nInfo filename too long, please re-enter: "); + } + + /* compute the basename of the info filename */ + /* remove the trailing newline */ + uuname = &infoname[strlen(infoname)-1]; + *uuname = '\0'; + /* avoid rindex/shrrchr compat issues, do it by hand */ + for (--uuname; uuname > infoname; --uuname) { + if (*uuname == '/') { + ++uuname; + break; + } + } + + /* attempt to open the info file */ + infile = fopen(infoname, "r"); + if (infile == NULL) { + fprintf(stderr, "\n%s: cannot open info file: %s: ", + program, infoname); + perror(""); + continue; + } + + /* + * write the start of the section + */ + fprintf(output, "---info---\n"); + check_io(output, oname, EOF_NOT_OK); + + /* uuencode the info file */ + uuencode(output, oname, infile, infoname, UUINFO_MODE, uuname); + + printf("\nDo you have another info file to include (enter y or n)? "); + while (get_line(yorn, 1+1, 0) <= 0 || !(yorn[0]=='y' || yorn[0]=='n')) { + printf("\nplease answer y or n: "); + } + }; + return; +} + +/* + * output_build - output the ---build--- section + * + * usage: + * output entry's output file stream + * oname name of the output file + * build open build file stream + * bname name of the build file + * + * Read the needed information from stdin, and write the build section. + */ +void +output_build(FILE *output, char *oname, FILE *build, char *bname) +{ + /* + * write the start of the section + */ + fprintf(output, "---build---\n"); + check_io(output, oname, EOF_NOT_OK); + + /* + * uuencode the program file + */ + uuencode(output, oname, build, bname, UUBUILD_MODE, UUBUILD_NAME); + return; +} + +/* + * output_program - output the ---program--- section + * + * usage: + * output entry's output file stream + * oname name of the output file + * prog open program stream + * pname name of program file + * + * Read the needed information form stdin, and write the program section. + */ +void +output_program(FILE *output, char *oname, FILE *prog, char *pname) +{ + /* + * write the start of the section + */ + fprintf(output, "---program---\n"); + check_io(output, oname, EOF_NOT_OK); + + /* + * uuencode the program file + */ + uuencode(output, oname, prog, pname, UUPROG_MODE, UUPROG_NAME); + return; +} + +/* + * output_end - output the ---end--- section + * + * usage: + * output entry's output file stream + * oname name of the output file + * + * Read the needed information form stdin, and write the 'end section'. + */ +void +output_end(FILE *output, char *oname) +{ + /* + * write the final section terminator + */ + fprintf(output, "---end---\n"); + check_io(output, oname, EOF_NOT_OK); + return; +} + +/* + * get_line - get an answer from stdin + * + * usage: + * buf input buffer + * siz length of input, including the newline + * maxcol max col allowed, 0 => disable check + * + * This function will flush stdout, in case a prompt is pending, and + * read in the answer. + * + * This function returns 0 if the line is too long, of the length of the + * line (including the newline) of the line was ok. This function does + * not return if ERROR or EOF. + */ +int +get_line(char *buf, int siz, int maxcol) +{ + int length; /* the length of the input line */ + + /* flush terminal output */ + fflush(stdout); + + /* read the line */ + if (fgets(buf, siz+1, stdin) == NULL) { + /* report the problem */ + check_io(stdin, "stdin", EOF_NOT_OK); + } + + /* look for the newline */ + length = strlen(buf); + if (buf[length-1] != '\n') { + int eatchar; /* the char being eaten */ + + /* no newline found, line must be too long, eat the rest of the line */ + do { + eatchar = fgetc(stdin); + } while (eatchar != EOF && eatchar != '\n'); + check_io(stdin, "stdin", EOF_NOT_OK); + + /* report the situation */ + return 0; + } + + /* watch for long lines, if needed */ + if (maxcol > 0 && (length > maxcol || col_len(buf) > maxcol)) { + /* report the situation */ + return 0; + } + + /* return length */ + return length; +} + +/* + * output_till_dot - output a set of lines until '.' by itself is read + * + * usage: + * output entry's output file stream + * oname name of the output file + * leader the lead text for the first line + * + * This routine will read a set of lines until (but not including) + * a single line with '.' is read. The format of the output is: + * + * leader:\tfirst line + * \tnext line + * \tnext line + * ... + * + * This routine will not return if I/O error or EOF. + */ +void +output_till_dot(FILE *output, char *oname, char *leader) +{ + char buf[BUFSIZ+1]; /* input buffer */ + int count; /* lines read */ + int done=FALSE; /* TRUE => finished reading input */ + + /* instruct the user on how to input */ + printf("\nTo end input, enter a line with a single period.\n"); + + /* read lines until '.' or EOF */ + count = 0; + while (!done) { + /* issue the prompt */ + printf("%s\t", (count>0) ? "" : leader); + fflush(stdout); + + /* get the line */ + if (get_line(buf, BUFSIZ, MAX_COL-9) <= 0) { + printf("\nline too long, please re-enter:\n\t"); + continue; + } + + /* note if '.' was read */ + if (strcmp(buf, ".\n") == 0) { + done = TRUE; + } + + /* write line if we read something */ + if (!done) { + fprintf(output, "%s\t%s", (count++>0) ? "" : leader, buf); + check_io(output, oname, EOF_NOT_OK); + } + } + + /* if no lines read, at least output something */ + if (count <= 0) { + fprintf(output, "%s\t.\n", leader); + check_io(output, oname, EOF_NOT_OK); + } + return; +} + +/* + * col_len - determine the highest that a string would reach + * + * usage: + * string the string to examine + * + * Given a string, this routine returns that a string would reach + * if the string were printed at column 1. Tab stops are assumed + * to start at 9, 17, 25, 33, ... + */ +int +col_len(char *string) +{ + int col; /* current column */ + char *p; /* current char */ + + /* scan the string */ + for (col=0, p=string; *p != '\0' && *p != '\n'; ++p) { + /* note the column shift */ + col = (*p=='\t') ? 1+((col+8)/8*8) : col+1; + } + if (*p == '\n') { + --col; + } + + /* return the highest column */ + return col; +} + +/* + * check_io - check for EOF or I/O error on a stream + * + * usage: + * stream the stream to check + * name the name of this stream + * eof_ok EOF_OK or EOF_NOT_OK + * + * Does not return if EOF or I/O error. + */ +void +check_io(FILE *stream, char *name, int eof_ok) +{ + /* test for I/O error */ + if (ferror(stream)) { + fprintf(stderr, "%s: error on %s: ", program, name); + perror(""); + exit(1); + + /* test for EOF */ + } else if (eof_ok == EOF_NOT_OK && feof(stream)) { + fprintf(stderr, "%s: EOF on %s\n", program, name); + exit(1); + } + return; +} + +/* + * uuencode - uuencode a file + * + * usage: + * output output file stream + * oname output filename + * infile input file stream + * iname input filename + * umode the mode to put on the uuencode file + * uname name to put on the uuencode file + * + * Perform the uuencoding process identical to the process performed + * by the uuencode(1) utility. + * + * This routine implements the algorithm described in the uuencode(5) + * 4.3BSD Reno man page. + */ +void +uuencode(FILE *output, char *oname, FILE *infile, + char *iname, int umode, char *uname) +{ + char buf[UUENCODE_LEN+1]; /* the uuencode buffer */ + int read_len; /* actual number of chars read */ + int val; /* 6 bit chunk from buf */ + char filler='\0'; /* filler uuencode pad text */ + char *p; + + /* + * output the initial uuencode header + */ + fprintf(output, "begin %o %s\n", umode, uname); + check_io(output, oname, EOF_NOT_OK); + + /* + * clear out the input buffer + */ + for (p=buf; p < &buf[sizeof(buf)/sizeof(buf[0])]; ++p) { + *p = '\0'; + } + + /* + * We will process UUENCODE_LEN chars at a time, forming + * a single output line each time. + */ + while ((read_len=fread(buf,sizeof(buf[0]),UUENCODE_LEN,infile)) > 0) { + + /* + * the first character is the length character + */ + fputc(UUENCODE(read_len), output); + check_io(output, oname, EOF_NOT_OK); + + /* + * We will convert 24 bits at a time. Thus we will convert + * 3 sets of 8 bits into 4 sets of uuencoded 6 bits. + */ + for (p=buf; read_len>0; read_len-=3, p+=3) { + + /* bits 0 to 5 */ + val = (p[0]>>2)&0x3f; + fputc(UUENCODE(val), output); + check_io(output, oname, EOF_NOT_OK); + + /* bits 6 to 11 */ + val = ((p[0]<<4)&0x30) | ((p[1]>>4)&0x0f); + fputc(UUENCODE(val), output); + check_io(output, oname, EOF_NOT_OK); + + /* bits 12 to 17 */ + val = ((p[1]<<2)&0x3c) | ((p[2]>>6)&0x03); + fputc(UUENCODE(val), output); + check_io(output, oname, EOF_NOT_OK); + + /* bits 18 to 23 */ + val = p[2]&0x3f; + fputc(UUENCODE(val), output); + check_io(output, oname, EOF_NOT_OK); + } + + /* end of UUENCODE_LEN line */ + fputc('\n', output); + check_io(output, oname, EOF_NOT_OK); + + /* + * clear out the input buffer (don't depend on bzero() or memset()) + */ + for (p=buf; p < &buf[sizeof(buf)/sizeof(buf[0])]; ++p) { + *p = '\0'; + } + } + + /* check the last read on the input file */ + check_io(infile, iname, EOF_OK); + + /* write end of uuencode file */ + fprintf(output, "%c\nend\n", UUENCODE(filler)); + check_io(output, oname, EOF_NOT_OK); +} diff --git a/2001/anonymous/.gitignore b/2001/anonymous/.gitignore index 67f3bd25f..49b1e5d70 100644 --- a/2001/anonymous/.gitignore +++ b/2001/anonymous/.gitignore @@ -1,2 +1,6 @@ anonymous anonymous.ten +ten.bak.od +ten.bak.txt +ten.od +ten.txt diff --git a/2001/anonymous/Makefile b/2001/anonymous/Makefile index e4232e6cb..eb0530ae1 100644 --- a/2001/anonymous/Makefile +++ b/2001/anonymous/Makefile @@ -70,7 +70,7 @@ CINCLUDE= # Optimization # -OPT= -O1 +OPT= # Default flags for ANSI C compilation # @@ -116,8 +116,8 @@ ENTRY= anonymous PROG= ${ENTRY} # OBJ= ${PROG}.o -DATA= anonymous.ten.c -TARGET= ${PROG} +DATA= +TARGET= ${PROG} ${PROG}.ten # ALT_OBJ= ALT_TARGET= @@ -135,13 +135,27 @@ all: data ${TARGET} supernova deep_magic magic charon pluto ${PROG}: ${PROG}.c - @echo "NOTE: this entry seems to no longer work." magic='${CC} ${CFLAGS}'; \ X='-DA(X)=#X'; \ warning='-Dprocessor'; \ $$magic $$warning -Dmagic= $$X "-DX=A($$magic \"$$X\")" \ $< -o $@ ${LIBS} + +${PROG}.ten: ${PROG}.ten.c + @echo "WARNING: ${PROG}.ten.c must be compiled as 32-bit to use with the entry itself;" + @echo "this is because the program works on 32-bit binaries. If you cannot use -m32 this" + @echo "will NOT work!" + @echo + @echo "If you want to use it where this is not possible e.g. with a Mac, say to" + @echo "use by itself, try:" + @echo + @echo " ${CC} $< -o $@" + @echo + @echo "but running ${PROG} on the resulting binary will crash." + @echo + ${CC} ${CFLAGS} -m32 $< -o $@ ${LIBS} + # alternative executable # alt: data ${ALT_TARGET} @@ -171,6 +185,7 @@ clean: clobber: clean ${RM} -f ${TARGET} ${ALT_TARGET} + ${RM} -f anonymous.ten.bak ten.od ten.od.bak ten.txt ten.bak.txt @-if [ -e sandwich ]; then \ ${RM} -f sandwich; \ echo 'ate sandwich'; \ diff --git a/2001/anonymous/README.md b/2001/anonymous/README.md index 016d4e15d..50b503455 100644 --- a/2001/anonymous/README.md +++ b/2001/anonymous/README.md @@ -1,7 +1,7 @@ # Most likely to amaze - The author wishes to remain anonymous - Great Britain +The author wishes to remain anonymous +Great Britain ## To build: @@ -12,29 +12,73 @@ make ## To run: ```sh -./anonymous program +./anonymous x86_program ``` -NOTE: this entry seems to no longer work. [Cody Boone -Ferguson](/winners.html#Cody_Boone_Ferguson) has offered some tips in the -[bugs.md](/bugs.md) file for anyone who mights want to try and fix this but it -seems to require a lot of parsing, debugging, an x86 system and possibly knowing -the internals of the ELF format (x86 specific). You need to run the program on a -binary to test. See the try section below for a program that, if you get the -entry to work, would be okay to test it on. Thank you and we will happily credit -you if you fix this. +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed both the +supplementary program and the program itself, both of which segfaulted. He +managed to do this with linux but it will not work with macOS (see +[bugs.md](/bugs.md) for why this is); this is not a bug but a feature inherent +in what it does. He said this took serious debugging and skill (shameless self +promotion but it's true :-) ) and we thank him _very much_! But what needed to +be changed? Although it took a fair bit of debugging it turns out all that +needed to be changed was: -WARNING: if you do get this to work it will destroy files that it is used on. -See the author's warning on this. +- `#include ` for `mmap()`. +- have `main()` call another function which is the recursive function; this +prevented `main()` from entering an infinite loop. +Without either of these it would crash and prevent modification of the 32-bit +[ELF](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) (not elf :-) +) binary. The following change was also made to be more portable, in case the +constants `PROT_READ` and/or `PROT_WRITE` are not standardised: + +Change `3` in the call to `mmap()` to be `PROT_READ|PROT_WRITE`: just in case +`PROT_READ|PROT_WRITE` does not equal 3 (though it seems to be equal in both +macOS and linux). + +NOTE: there might be educational value to see the progress of this fix; if you +wish to see, try: + +```sh +git diff d2a42f42e8f477f29e9d5ed09ce2bb349eaf7397..93aa8d79f208dcccc3c5a2370a727b5cf64e9c53 anonymous.c +git diff 93aa8d79f208dcccc3c5a2370a727b5cf64e9c53..c48629017117379a52b1a512ef8f2593ca9569c8 anonymous.c +git diff c48629017117379a52b1a512ef8f2593ca9569c8..efdee208a2bc650256637b9357ddfd0de82d2f41 anonymous.c +git diff efdee208a2bc650256637b9357ddfd0de82d2f41..e9a3f77ea3b209e63ac3f9c06bb84ad86e5ea706 anonymous.c +``` + +### WARNING on note from the author + +The author suggested that this will somewhat destroy the binaries this touches +but Cody did not observe this. It does indeed modify the files as the script +below will show you (though not all files are modified: can you figure out why +that is?) but Cody did not notice any problems in using them. Perhaps it's +something he's not aware of. If you follow the try commands below you will +notice that although the binaries do differ it's not many differences. See the +author's warning about this. + +### INABIAF - it's not a bug it's a feature! :-) + +This entry will not work on 64-bit binaries! The program itself can be compiled +as 64-bit but the files it processes must be 32-bit ELF binaries. Not doing this +will likely cause a crash or cause your computer to [halt and catch +fire](https://en.wikipedia.org/wiki/Halt_and_Catch_Fire_(computing)! :-) + +This entry will also very likely crash if no arg is specified. It might do +something funny if you run it on itself as well but see below :-) ## Try: ```sh -make anonymous.ten -./anonymous anonymous.ten +./try.me.sh ``` +What happens if the x86 program has already been modified by this program? + +What happens if you try it on another file like [anonymous.c](anonymous.c)? Can +you recompile it okay? What if you run it on `anonymous` itself? Can you run the +program successfully after it without recompiling? + ## Judges' remarks: @@ -46,7 +90,8 @@ quite a lot of bit twiddling. This program is an optimizing dynamic binary translator, allowing you to run x86 programs on any machine (x86 or otherwise). -I have included a simple "10 green bottles" program, already compiled +I have included a simple [10 green +bottles](https://www.bbc.co.uk/teach/school-radio/nursery-rhymes-ten-green-bottles/zncyt39) program, already compiled for the x86. The program 'ten', and its source (dull) are given as info files. Warning: note that the translator screws around with the binary you run on it, *will* corrupt the binary to some extent, and may leave @@ -88,75 +133,75 @@ switches such that while compiling the program it generates one error compiler errors while it is running (yes, the program can generate compiler errors while it is running). If you do not wish to see this error, or if the program generates any further error when compiled using -your C compiler please remove the "warning=..." line from the build -script. +your C compiler please remove the `-Dwarning='-Dprocessor'` line and the +`$$warning` from the compiler invocation. -### Optimization: +### Optimization -The build script contains a "-O1" switch for the compiler. Increasing +The build script contains a `-O1` switch for the compiler. Increasing the optimization level will make the program run *slower*, while compiling the program without any optimization will allow it to run *faster*. -### Obfuscation: +### Obfuscation -The most obvious part of the obfuscation is probably the mess of defines -at the top. This may seem a somewhat tired old obfuscation - however -since many of these macros are (sometimes only) used by the program once -it has dynamically recompiled itself, they are only referenced within -the source code from within strings - and therefore the macros cannot be -expanded. Furthermore, some of these strings of code are not given as -strings, but instead are wrapped up in macros that use the "#" -preprocessor operator to turn them into strings. In the hope throwing a -few C beautifiers the macro to generate the strings is not contained -within the source code but instead is passed in on the command line. +The most obvious part of the obfuscation is probably the mess of defines at the +top. This may seem a somewhat tired old obfuscation - however since many of +these macros are (sometimes only) used by the program once it has dynamically +recompiled itself, they are only referenced within the source code from within +strings - and therefore the macros cannot be expanded. Furthermore, some of +these strings of code are not given as strings, but instead are wrapped up in +macros that use the `#` preprocessor operator to turn them into strings. In the +hope of throwing off a few C beautifiers the macro to generate the strings is +not contained within the source code but instead is passed in on the command +line. Buried under all this, and the fact that the entire program is just a -call to exit, there are some nice subtle little obfuscations. For +call to `exit()`, there are some nice subtle little obfuscations. For example, you may notice that there are a couple of macros that use the -"##" preprocessor operator to build pairs of functions. One of these +`##` preprocessor operator to build pairs of functions. One of these macros is used to build to pairs of functions of which only one has local variables which shadow global variables; so one modifies the global state, and the other doesn't. -There is also quite a nice trick where I wave a magic wand, and a chunk -of code which should only be run when the program is run for the first -time (setting the PC to point at main, etc) gets turned into a -frog^M^M^M^Mstring. The C compiler sees a string by itself in the code, -thinks "yup, that's a valid C expression", and quietly moves on to the -next line of code. +There is also quite a nice trick where I wave a magic wand, and a chunk of code +which should only be run when the program is run for the first time (setting the +[PC / IP](https://en.wikipedia.org/wiki/Program_counter) to point at `main()`, +etc) gets turned into a `frog^M^M^M^Mstring`. The C compiler sees a string by +itself in the code, thinks "yup, that's a valid C expression", and quietly moves +on to the next line of code. -### Limitations: +### Limitations -Due to space limitations only a handful of instructions are supported, -those instructions which are supported may supported in somewhat -non-conventional ways, chunks of the architecture (e.g. flags) are just +Due to space limitations only a handful of instructions are supported; +these instructions which are supported are supported in somewhat +non-conventional ways: chunks of the architecture (e.g. flags) are just ignored, the elf loader does not really load the elf binary, the target library linking can only pass up to 3 parameters to the target library -function, etc, etc, etc. +function, etc. In short, please consider this a full disclaimer for any bug that may turn up - yes the program is unsafe, but it's pretty cool anyway. -Despite all this, the translator is not exclusively limited to running -the 'ten' program. Other trivial x86 programs may run on the translator -\- and I have successfully run a wide range of HelloWorld programs, -including one of last years IOCCC winners, 'tomx'. +Despite all this, the translator is not exclusively limited to running the +[anonymous.ten](anonymous.ten.c) program. Other trivial **_x86_** programs may +run on the translator \- and I have successfully run a wide range of "Hello +World" programs, including one of last years IOCCC winners, +[tomx](/2000/tomx/tomx.c). -### Complete Program: +### Complete Program -The fact that the program makes calls to system and execv may imply that -it is not a complete program in its own right, as it relies on other -programs. The call to system is a call to ask gcc to recompile the -translator with a new set of switches, and the call to execv asks for -the newly compiled program to be executed. I would point out that -almost every other entry to this competition also require a C compiler -(well, the published winners at any rate, and I recognize that a few -don't). There is little real difference between this program and one -like last years entry 'dhyang'; both are just C programs that generate C -code as their output. +The fact that the program makes calls to `system()` and `execv()` may imply that +it is not a complete program in its own right, as it relies on other programs. +The call to `system()` is a call to ask gcc to recompile the translator with a +new set of switches, and the call to `execv()` asks for the newly compiled +program to be executed. I would point out that almost every other entry to this +competition also require a C compiler (well, the published winners at any rate, +and I recognize that a few don't). There is little real difference between this +program and one like last years entry [dhyang](/2000/dhyang/dhyang.c); both are +just C programs that generate C code as their output. -Enjoy, thanks! +Enjoy and thanks! ## Copyright and CC BY-SA 4.0 License: diff --git a/2001/anonymous/anonymous.c b/2001/anonymous/anonymous.c index 7572a0776..519f03c8e 100644 --- a/2001/anonymous/anonymous.c +++ b/2001/anonymous/anonymous.c @@ -4,6 +4,7 @@ #include #include #include +#include #define l int* #define F char @@ -36,6 +37,11 @@ E(DX) { c *z? DX:DX <<030|(DX&65280)<<010|DX>>8&65280|DX>>24&0377; } l K(k){ c L(E(k [(l)V(17)]),0); } V(v){ c E(B[v]); } int -main (int cka, char **k) { char *ck = (char *)cka; - exit(E((ck?main((z?(stat(M,&t)?P+=a+'{'?0:3:execv(M,k),a=G,i=P,y=G&255,sprintf(Q,y/'@'-3?A(*L(V(%d+%d)+%d,0)):A(R[%d]),(y&7),'\r',y/0100-1?0:G),(a+127&&a+'}'&&a+1?(a+61&&a+24&&a+025?(P=a+'H'&&a%061<=0?P:i,D(a>0?" R[%d]=E(~-E(R[%d])),\0 U R[%d],\0 R[%d] O,\0 U %d,\0R[%d]=0,"+(a&'8')*3:a <- 'c'?" %d, %c%s = R[%d], \0 %d, *R=%c%s==R[%d], \0 R[%d]=(int)%c%s,"-a%'w'%'j'*5:"%d,%d,%s=%d,",a>0?a-'h'?a-49?a&7:g:I:g,a>0?a&7:"& "[a%3%2+1],a+72?Q:A(*R),a>0|a<-99?g:I,0)):(P=i,i=a+61?a+21?E(I):G:0,D(a%' '+29+"P O,\0 U %d,P=%d,",P,P+i,0,0,0),p(d,"A'",b))):(n=g-4?g%5-1?a+127?G:I:0:(Scan(),*( x86?processor :d)=0,(int)(ss+V(i))),g%5<2?D(g%5?" %s=E(~-E(%s)), \0 U %s,"+4*g:"%s=E(E(%s)%c%d),",Q,Q,"+ - "[g],n,0):(a=G-'u'?'!':'=',D(g-4?"P=%d%c=%s?%d:%d,":"*R=E(((int(*)(l,l,l))%s)(K(1),K(2),K(3))),P O,",n,a,Q,P,P+G),p(d,"A'",b))))):(Run((z=(F*)&ck,stat(k[1],&t),B=(l)mmap(0,i=t.st_size,3,1,open(k[1],2),0))),magic((R[4]=E(B+i/4),run(),P=V(-~i),U 0)),sprintf(M,A(.%s%d),k[1],P),D("%s %s '-DX=A(%s)' -o %s '-Dmagic=",X,__FILE__,X,M,fflush(0)))),k):p(M,A(rm -f .%s*),M),*R))); +pain(char *ck, char **k) +{ +return (z?(stat(M,&t)?P+=a+'{'?0:3:execv(M,k),a=(signed char)E(*L(P++,0)),i=P,y=(signed char)E(*L(P++,0))&255,sprintf(Q,y/'@'-3?"*L(V(%d+%d)+%d,0)":"R[%d]",(y&7),'\r',y/0100-1?0:(signed char)E(*L(P++,0))),(a+127&&a+'}'&&a+1?(a+61&&a+24&&a+025?(P=a+'H'&&a%061<=0?P:i,d+=sprintf( d,a>0?" R[%d]=E(~-E(R[%d])),\0 U R[%d],\0 R[%d] O,\0 U %d,\0R[%d]=0,"+(a&'8')*3:a <- 'c'?" %d, %c%s = R[%d], \0 %d, *R=%c%s==R[%d], \0 R[%d]=(int)%c%s,"-a%'w'%'j'*5:"%d,%d,%s=%d,",a>0?a-'h'?a-49?a&7:(y/010&7):(P+=4,*L(P-4,0)):(y/010&7),a>0?a&7:"& "[a%3%2+1],a+72?Q:"*R",a>0|a<-99?(y/010&7):(P+=4,*L(P-4,0)),0 ),(char* ) P):(P=i,i=a+61?a+21?E((P+=4,*L(P-4,0))):(signed char)E(*L(P++,0)):0,d+=sprintf( d,a%' '+29+"P O,\0 U %d,P=%d,",P,P+i,0,0,0 ),(char* ) P,system((sprintf(d,"A'",k[1]),b)),z)):(n=(y/010&7)-4?(y/010&7)%5-1?a+127?(signed char)E(*L(P++,0)):(P+=4,*L(P-4,0)):0:(Scan(),*( (char*)index(ss+V(i ),0100)?(char*)index(ss+V(i ),0100) :d)=0,(int)(ss+V(i))),(y/010&7)%5<2?d+=sprintf( d,(y/010&7)%5?" %s=E(~-E(%s)), \0 U %s,"+4*(y/010&7):"%s=E(E(%s)%c%d),",Q,Q,"+ - "[(y/010&7)],n,0 ),(char* ) P:(a=(signed char)E(*L(P++,0))-'u'?'!':'=',d+=sprintf( d,(y/010&7)-4?"P=%d%c=%s?%d:%d,":"*R=E(((int(*)(l,l,l))%s)(K(1),K(2),K(3))),P O,",n,a,Q,P,P+(signed char)E(*L(P++,0)) ),(char* ) P,system((sprintf(d,"A'",k[1]),b)),z)))):(Run((z=(char*)&ck,stat(k[1],&t),B=(l)mmap(0,i=t.st_size,PROT_READ|PROT_WRITE,1,open(k[1],2),0))),(((B+13)[4]=E(B+i/4),run(),P=V(-~i),(B+13)[4]=E(V(17)-4),*(int*)V(021))),sprintf(M,".%s%d",k[1],P),d+=sprintf( d,"%s %s '-DX=A(%s)' -o %s '-Dmagic=","cpp -std=gnu99 -Wall -Wextra -pedantic -Winfinite-recursion -Wno-bitwise-conditional-parentheses -Wno-error -Wno-implicit-function-declaration -Wno-implicit-int -Wno-int-to-pointer-cast -Wno-macro-redefined -Wno-pedantic -Wno-pointer-to-int-cast -Wno-return-type -Wno-string-plus-int -Wno-bitwise-op-parentheses -Wno-format -Wno-format-extra-args -Wno-int-conversion -Wno-unused-parameter -Wno-unsequenced -E \"-DA(X)=#X\"","anonymous.c","cpp -std=gnu99 -Wall -Wextra -pedantic -Winfinite-recursion -Wno-bitwise-conditional-parentheses -Wno-error -Wno-implicit-function-declaration -Wno-implicit-int -Wno-int-to-pointer-cast -Wno-macro-redefined -Wno-pedantic -Wno-pointer-to-int-cast -Wno-return-type -Wno-string-plus-int -Wno-bitwise-op-parentheses -Wno-format -Wno-format-extra-args -Wno-int-conversion -Wno-unused-parameter -Wno-unsequenced -E \"-DA(X)=#X\"",M,fflush(0) ),(char* ) P)); +} +int +main (int cka, char **k) { char *ck = (char *)cka; + exit(E((ck?pain((char*)cka,k):system((sprintf(M,"rm -f .%s*",k[1]),M)),z,*(B+13)))); } diff --git a/2001/anonymous/anonymous.ten.c b/2001/anonymous/anonymous.ten.c index e80570852..e04589bd9 100644 --- a/2001/anonymous/anonymous.ten.c +++ b/2001/anonymous/anonymous.ten.c @@ -1,3 +1,4 @@ +#include #define PLURAL(bottles) bottles==1?"bottle":"bottles" void sing(int bottles) { diff --git a/2001/anonymous/try.me.sh b/2001/anonymous/try.me.sh new file mode 100755 index 000000000..4cc1af804 --- /dev/null +++ b/2001/anonymous/try.me.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +make clobber +make all 2>/dev/null +echo "$ cp anonymous.ten anonymous.ten.bak" 1>2 +cp anonymous.ten anonymous.ten.bak +echo "$ ./anonymous anonymous.ten" 1>&2 +./anonymous anonymous.ten +echo "$ ./anonymous.ten" 1>&2 +./anonymous.ten +echo "$ diff -s anonymous.ten anonymous.ten.bak" 1>&2 +diff -s anonymous.ten anonymous.ten.bak +echo "$ od anonymous.ten > ten.od" 1>&2 +od anonymous.ten > ten.od +echo "$ od anonymous.ten.bak > ten.bak.od" 1>&2 +od anonymous.ten.bak > ten.bak.od +echo "$ diff ten.bak.od ten.od" 1>&2 +diff ten.bak.od ten.od +echo "$ ./anonymous.ten > ten.txt" 1>&2 +./anonymous.ten > ten.txt +echo "$ ./anonymous.ten.bak > ten.bak.txt" 1>&2 +./anonymous.ten.bak > ten.bak.txt +echo "$ diff -s ten.txt ten.bak.txt" 1>&2 +diff -s ten.txt ten.bak.txt diff --git a/2001/bellard/.gitignore b/2001/bellard/.gitignore index baa3302b3..52488cedd 100644 --- a/2001/bellard/.gitignore +++ b/2001/bellard/.gitignore @@ -1,2 +1,3 @@ bellard bellard.otccex +otccelf diff --git a/2001/bellard/Makefile b/2001/bellard/Makefile index 2fb739b3d..c4634b8d4 100644 --- a/2001/bellard/Makefile +++ b/2001/bellard/Makefile @@ -55,7 +55,7 @@ CSTD= -std=gnu99 # Some entries require 32-bitness: ARCH= -m32 # Some entries require 64-bitness: ARCH= -m64 # -ARCH= +ARCH= # Defines that are needed to compile # @@ -71,7 +71,7 @@ OPT= -O3 # Default flags for ANSI C compilation # -CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${OPT} -rdynamic +CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${OPT} -rdynamic -fno-pie # Libraries needed to build # @@ -131,6 +131,11 @@ all: data ${TARGET} supernova deep_magic magic charon pluto ${PROG}: ${PROG}.c + @echo "WARNING: ${PROG}.c must be compiled as 32-bit to use with the entry itself;" + @echo "if you cannot use -m32 this will NOT work!" + ${CC} ${CFLAGS} -m32 $< -o $@ ${LIBS} + +${PROG}.otccex: ${PROG}.otccex.c ${CC} ${CFLAGS} $< -o $@ ${LIBS} # alternative executable diff --git a/2001/bellard/README.md b/2001/bellard/README.md index 882040106..407ba683a 100644 --- a/2001/bellard/README.md +++ b/2001/bellard/README.md @@ -1,11 +1,10 @@ # Best abuse of the rules - Fabrice Bellard - 451 chemin du mas de Matour - 34790 GRABELS - France - - http://bellard.org +Fabrice Bellard +451 chemin du mas de Matour +34790 Grabels +France + ## To build: @@ -20,14 +19,35 @@ make ``` [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) partially fixed this -but he notes that this will not work without some serious debugging. As he has -no 32-bit system to test this under it's also unlikely he will be able to -resolve the remaining problems. He also has no knowledge of the ELF binary -format so that will also make it harder to work. As it is it segfaults. He fixed -an earlier segfault so that at least the file can be opened and he also changed -some of the macro uses to what they expanded to but mostly he kept it the same. -He also fixed `bellard.otccex.c` so it does not segfault and seemingly works -okay. Thank you Cody for your assistance! +but he notes that this will not work without (according to the author) i386 +linux or else some skill in resolving the portability issues. As it is it +segfaults in 64-bit linux (and as expected macOS). He fixed an earlier segfault +so that at least the file can be opened (but perhaps that will be wrong in i386 +linux?) and he also changed some of the macro used to what they evaluate to but +mostly he kept it the same. + +Cody also fixed [bellard.otccex.c](bellard.otccex.c) so it does not segfault and +seemingly works okay (it did not work at all). The main problem was that some +ints were being used as pointers. Also the Fibonacci sequence (`fib()`) will +overflow at `n > 48` so this is checked prior to running the function. Either +way unfortunately this entry seems to not work in 64-bit linux or macOS. See +below portability notes. Thank you Cody for your assistance! + + +### Portability notes: + +With a tip from [Yusuke Endoh](/winners.html#Yusuke_Endoh) we rediscovered the +author's [web page for this program](https://bellard.org/otcc/) where it is +stated that this will only work in i386 linux. The author also stated in the +remarks in this document that they used [gcc +2.95.2](https://ftp.gnu.org/gnu/gcc/gcc-2.95.2/gcc-everything-2.95.2.tar.gz) but +we don't know if that's relevant or not. + +Yusuke offered a modification which is not needed with gcc but with some +versions of `clang` it is. With `gcc` we can get away with `-rdynamic -fno-pie +-Wl,-z,execstack` which solves the problem of execution in memory but any +compiler that does not support this would not work. Thus we use the modification +by Yusuke. Thank you Yusuke! ## Try: @@ -38,129 +58,130 @@ okay. Thank you Cody for your assistance! ## Judges' remarks: - :-) +`` :-) ## Author's remarks: - OTCC is an Obfuscated Tiny C Compiler for i386-linux. It generates - FAST! i386 32 bit code (no bytecode) and it is powerful enough to - compile itself. OTCC supports a strict subset of C. This subset is - compilable by a standard ANSI C compiler. OTCC compiles, - assembles, links and runs C code without the need of any other - program. +`OTCC` is an Obfuscated Tiny C Compiler for i386-linux. It generates +FAST! i386 32 bit code (no bytecode) and it is powerful enough to +compile itself. `OTCC` supports a strict subset of C. This subset is +compilable by a standard ANSI C compiler. `OTCC` compiles, +assembles, links and runs C code without the need of any other +program. - You can use it by typing: +You can use it by typing: - ./bellard bellard.c [args]... +```sh +./bellard bellard.c [args]... +``` - or by giving the C source to its standard input. +or by giving the C source to its standard input. - 'args' are given to the 'main' function of bellard.c (argv[0] is - bellard.c). +`args` are given to the `main` function of `bellard.c` (`argv[0]` is +[bellard.c](bellard.c)). - Examples: +### Examples: - - Sample compilation and execution: +- Sample compilation and execution: ./bellard bellard.otccex.c 10 - - Self compilation: +- Self compilation: ./bellard bellard.c bellard.otccex.c 10 - - Self compilation iterated... +- Self compilation iterated... ./bellard bellard.c bellard.c bellard.otccex.c 10 - + An alternate syntax is to use it as a script interpreter: you can - put '#!/usr/local/bin/otcc' at the beginning of your C source if - you installed otcc at this place. + put `#!/usr/local/bin/otcc` at the beginning of your C source if + you installed `otcc` at this place. - Supported C language subset (read joint example 'otccex.c' to have - an introduction to OTCC dialect): +### Supported C language subset (read joint example [bellard.otccex.c](bellard.otccex.c) to have an introduction to `OTCC` dialect) - - Expressions: +#### Expressions: - * binary operators, by decreasing priority order: '*' '/' '%', - '+' '-', '>>' '<<', '<' '<=' '>' '>=', '==' '!=', '&', - '^', '|', '=', '&&', '||'. +* binary operators, by decreasing priority order: `*` `/` `%`, + `+` `-`, `>>` `<<`, `<` `<=` `>` `>=`, `==` `!=`, `&`, + `^`, `|`, `=`, `&&`, `||`. - * '&&' and '||' have the same semantics as C : left to right - evaluation and early exit. +* `&&` and `||` have the same semantics as in C: left to right + evaluation and early exit. - * Parenthesis are supported. +* Parenthesis are supported. - * Unary operators: '&', '*' (pointer indirection), '-' - (negation), '+', '!', '~', post fixed '++' and '--'. +* Unary operators: `&`, `*` (pointer indirection), `-` + (negation), `+`, `!`, `~`, post fixed `++` and `--`. - * Pointer indirection ('*') only works with explicit cast to - 'char *', 'int *' or 'int (*)()' (function pointer). +* Pointer indirection (`*`) only works with explicit cast to + `char *`, `int *` or `int (*)()` (function pointer). - * '++', '--', and unary '&' can only be used with variable - lvalue (left value). +* `++`, `--`, and unary `&` can only be used with variable + lvalue (left value). - * '=' can only be used with variable or '*' (pointer - indirection) lvalue. +* `=` can only be used with variable or `*` (pointer + indirection) lvalue. - * Function calls are supported with standard i386 calling - convention. Function pointers are supported with explicit - cast. Functions can be used before being declared. +* Function calls are supported _with standard **i386** calling + convention_. Function pointers are supported _with explicit + cast_. Functions can be used before being declared. - - Types: only signed integer ('int') variables and functions can - be declared. Variables cannot be initialized in - declarations. Only old K&R function declarations are parsed - (implicit integer return value and no types on arguments). +- Types: only signed integer (`int`) variables and functions can + be declared. Variables cannot be initialized in + declarations. _Only old K&R function declarations are parsed + (implicit integer return value and no types on arguments)_. - - Any function or variable from the libc can be used because OTCC - uses the libc dynamic linker to resolve undefined symbols. +- Any function or variable from the libc can be used because `OTCC` + uses the libc dynamic linker to resolve undefined symbols. - - Instructions: blocks ('{' '}') are supported as in C. 'if' and - 'else' can be used for tests. The 'while' and 'for' C constructs - are supported for loops. 'break' can be used to exit - loops. 'return' is used for the return value of a function. +- Instructions: blocks (`{` `}`) are supported as in C. `if` and + `else` can be used for tests. The `while` and `for` C looks are supported. + `break` can be used to exit loops. `return` is used for the return value of a + function. - - Identifiers are parsed the same way as C. Local variables are - handled, but there is no local name space (not a problem if - different names are used for local and global variables). +- Identifiers are parsed the same way as C. Local variables are + handled, but there is no local name space (not a problem if + different names are used for local and global variables). - - Numbers can be entered in decimal, hexadecimal ('0x' or '0X' - prefix), or octal ('0' prefix). +- Numbers can be entered in decimal, hexadecimal (`0x` or `0X` + prefix), or octal (`0` prefix). - - '#define' is supported without function like arguments. No macro - recursion is tolerated. Other preprocessor directives are - ignored. +- `#define` is supported without function like arguments. _No macro + recursion is tolerated_; _other preprocessor directives are + ignored_. - - C Strings and C character constants are supported. Only '\n', - '\"', '\'' and '\\' escapes are recognized. +- C Strings and C character constants are supported. Only `\n`, + `\"`, `\'` and `\\` escapes are recognized. - - C Comments can be used (but no C++ comments). +- C Comments can be used (but no C++ comments). - - No error is displayed if an incorrect program is given. +- No error is displayed if an incorrect program is given. - - Memory: the code, data, and symbol sizes are limited to 100KB - (it can be changed in the source code). +- Memory: the code, data, and symbol sizes are limited to 100KB + (it can be changed in the source code). - Obfuscation: +### Obfuscation: - No special effort was needed because obfuscation is almost - unavoidable for such a program :-) Defines must be used to - compress the code, and integrated i386 code generator leads to non - obvious code. +No special effort was needed because obfuscation is almost +unavoidable for such a program :-) Defines must be used to +compress the code, and integrated i386 code generator leads to non +obvious code. - Portability: +### Portability: - OTCC only works on i386 linux because it generates i386 code. OTCC - also relies on little endianness, unaligned memory accesses and - ASCII representation of characters. It also supposes that no valid - pointers are less than 512. If all those constraints are met, then - OTCC could be theoretically used to "cross compile", although no - such support is currently integrated. +`OTCC` only works on i386 linux because it generates i386 code. `OTCC` +also relies on little endianness, unaligned memory accesses and +ASCII representation of characters. It also supposes that no valid +pointers are less than 512. If all those constraints are met, then +`OTCC` could be theoretically used to "cross compile", although no +such support is currently integrated. - It was successfully compiled with gcc version 2.95.2. You get some - warnings because old K&R protos are used, some casts are implicit - and some functions are used before being defined. OTCC uses the - dynamic linker to resolve symbols with 'dlsym()', so '-ldl' must - be used as library when you compile it. +It was successfully compiled with gcc version 2.95.2. You get some +warnings because old K&R prototypes are used, some casts are implicit +and some functions are used before being defined. `OTCC` uses the +dynamic linker to resolve symbols with `dlsym()`, so `-ldl` must +be used when you compile and link it. ## Copyright and CC BY-SA 4.0 License: diff --git a/2001/bellard/bellard.c b/2001/bellard/bellard.c index 53b45e216..9871b95a2 100644 --- a/2001/bellard/bellard.c +++ b/2001/bellard/bellard.c @@ -1,6 +1,8 @@ #include #include #include +#include +#include #define k *(int*) #define a if( #define c ad() @@ -8,7 +10,7 @@ #define p while( #define x *(char*) #define b == -#define V =calloc(1,99999) +#define V =mmap(NULL, 99999, PROT_EXEC | PROT_WRITE | PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0) #define f () #define J return #define l ae( diff --git a/2001/bellard/bellard.otccex.c b/2001/bellard/bellard.otccex.c index 9fdb8075a..d2000a952 100644 --- a/2001/bellard/bellard.otccex.c +++ b/2001/bellard/bellard.otccex.c @@ -35,6 +35,7 @@ fact(n) /* local variables can be declared. Only 'int' type is supported */ int i, r; r = 1; + /* 'while' and 'for' loops are supported */ for(i=2;i<=n;i++) r = r * i; @@ -44,7 +45,7 @@ fact(n) /* Well, we could use printf, but it would be too easy */ print_num(n, b) { - int tab, p, c; + int *tab, *p, c; /* Numbers can be entered in decimal, hexadecimal ('0x' prefix) and octal ('0' prefix) */ /* more complex programs use malloc */ @@ -57,16 +58,16 @@ print_num(n, b) c = c + 'a' - 10; else c = c + '0'; - *(char *)p = c; + *p = c; p++; n = n / b; - /* 'break' is supported */ - if (n == 0) - break; + /* 'break' is supported */ + if (n == 0) + break; } while (p != tab) { p--; - printf("%c", *(char *)p); + printf("%c", *p); } free(tab); } @@ -76,9 +77,9 @@ main(int argc, char **argv) { /* no local name space is supported, but local variables ARE supported. As long as you do not use a globally defined - variable name as local variable (which is a bad habbit), you + variable name as local variable (which is a bad habit), you won't have any problem */ - int n, f, base; + int n, (*f)(), base; /* && and || operator have the same semantics as C (left to right evaluation and early exit) */ @@ -100,11 +101,13 @@ main(int argc, char **argv) return 1; } } - printf("fib(%d) = ", n); - print_num(fib(n), base); - printf("\n"); - - printf("fact(%d) = ", n); + printf("fib(%d) with base %d = ", base, n); + if (n > 48) { + printf("Overflow\n"); + } else { + print_num(fib(n), base); + } + printf("fact(%d) with base %d = ", base, n); if (n > 12) { printf("Overflow"); } else { diff --git a/2001/bellard/otccelf.c b/2001/bellard/otccelf.c new file mode 100644 index 000000000..713127096 --- /dev/null +++ b/2001/bellard/otccelf.c @@ -0,0 +1,621 @@ +#include +#include +#include +#include +#include +#define r *(char*) +#define b if( +#define t *(int*) +#define k else +#define u while( +#define g av() +#define c ax( +#define f == +#define aj =mmap(NULL, 99999, PROT_EXEC | PROT_WRITE | PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0) +#define j () +#define O return +#define l a) +#define A int +#define n 0) +#define o aw( +#define p 1) +#define q s) +A e,C,J,m,T,U,K,v,P,i,ak,Q,D,V,al,Z,G,R,y; +L(l{ +r D++=a; +} +w j{ +b V){ +m=r V++; +b m f 2){ +V=0; +m=al; +} +} +k m=fgetc(ak); +} +am j{ +O isalnum(m)|m f 95; +} +an j{ +b m f 92){ +w j; +b m f 110)m=10; +} +} +g{ +A a,s,h; +u isspace(m)|m f 35){ +b m f 35){ +w j; +g; +b e f 536){ +g; +L(32); +t e=1; +t(e+4)=D; +} +u m!=10){ +L(m); +w j; +} +L(m); +L(2); +} +w j; +} +J=0; +e=m; +b am j){ +L(32); +Z=D; +u am j){ +L(m); +w j; +} +b isdigit(e)){ +C=strtol(Z,0,n; +e=2; +} +k{ +r D=32; +e=strstr(Q,Z-p-Q; +r D=0; +e=e*8+256; +b e>536){ +e=T+e; +b t e f p{ +V=t(e+4); +al=m; +w j; +g; +} +} +} +} +k{ +w j; +b e f 39){ +e=2; +an j; +C=m; +w j; +w j; +} +k b e f 47&m f 42){ +w j; +u m){ +u m!=42)w j; +w j; +b m f 47)m=0; +} +w j; +g; +} +k{ +a="++#m--%am*@R<^1c/@%[_[H3c%@%[_[H3c+@.B#d-@%:_^BKd<>`/03e<=0f>=/f<@.f>@1f==&g!='g&&k||#l&@.BCh^@.BSi|@.B+j~@/%Yd!@&d*@b"; +u s=r a++){ +h=r a++; +C=0; +u(J=r a++-98)>8; +} +} +E(a,d){ +r a++=d; +r a++=d>>8; +r a++=d>>16; +r a++=d>>24; +} +ao(l{ +A d; +return(r a&255)|(r(a+p&255)<<8|(r(a+2)&255)<<16|(r(a+3)&255)<<24; +} +ap(a,z){ +A d; +u l{ +d=ao(l; +b r(a-p f 5){ +b z>=G&&z8){ +h=aa(a,h); +X(q; +} +k{ +o 80); +X(q; +o 89); +b s f 4|s f 5){ +aq(l; +} +k{ +o l; +b d f 37)o 146); +} +} +} +b h&&s>8){ +h=aa(a,h); +M(a^p; +I(5); +H(h); +M(l; +} +} +} +B j{ +X(11); +} +ac j{ +B j; +O aa(0,n; +} +S(q{ +A h,d,a; +b e f 288){ +g; +g; +h=ac j; +g; +S(q; +b e f 312){ +g; +d=I(n; +H(h); +S(q; +H(d); +} +k{ +H(h); +} +} +k b e f 352|e f 504){ +a=e; +g; +g; +b a f 352){ +d=v; +h=ac j; +} +k{ +b e!=59)B j; +g; +d=v; +h=0; +b e!=59)h=ac j; +g; +b e!=41){ +a=I(n; +B j; +I(d-v-5); +H(l; +d=a+4; +} +} +g; +S(&h); +I(d-v-5); +H(h); +} +k b e f 123){ +g; +ar(p; +u e!=125)S(q; +g; +} +k{ +b e f 448){ +g; +b e!=59)B j; +U=I(U); +} +k b e f 400){ +g; +t s=I(t q; +} +k b e!=59)B j; +g; +} +} +ar(q{ +A h; +u e f 256|e!=-1&!q{ +b e f 256){ +g; +u e!=59){ +b q{ +P=P+4; +t e=-P; +} +k{ +t e=i; +i=i+4; +} +g; +b e f 44)g; +} +g; +} +k{ +t e=v; +g; +g; +h=8; +u e!=41){ +t e=h; +h=h+4; +g; +b e f 44)g; +} +g; +U=P=0; +o 15042901); +h=x(60545,n; +S(n; +H(U); +o 50121); +E(h,P); +} +} +} +c d){ +E(i,d); +i=i+4; +} +ad(d,l{ +c d); +d=d+134512640; +c d); +c d); +c l; +c l; +} +ae(q{ +A a,h,d,N,z,F; +N=0; +a=Q; +u p{ +a++; +h=a; +u r a!=32&&a ## To build: @@ -15,9 +13,9 @@ make [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed this to work with clang by adding another function that is allowed to have a third arg as an int, not a `char **`. He chose pain() because it's a four letter word that would -match the format and because it's pain that clang forces this. :-) He also fixed -a segfault in the case that no arg is specified. Thank you Cody for your -assistance! +match the format and because it's pain that clang forces this. :-) This fix +makes a point of the author's notes on portability no longer valid, btw. Thank +you Cody for your assistance! ## To run: @@ -26,6 +24,11 @@ assistance! ./cheong digits ``` +### INABIAF - it's not a bug it's a feature! :-) + +This program will very likely crash or do something different without an arg. + + ## Try: ```sh @@ -34,6 +37,8 @@ assistance! ./cheong 05305265226926441255040573044986873789 ``` +## Judges' remarks: + Be sure to give an even number of digits in the argument. Add a leading 0 if needed. @@ -64,32 +69,38 @@ This program runs normally on any ANSI C compiler and is ASCII dependent. Strict compiling gives just one unavoidable warning: - > gcc -ansi -Wall cheong.c - cheong.c:3: warning: third argument of `main' should probably be `char **' +```sh +gcc -ansi -Wall cheong.c +cheong.c:3: warning: third argument of `main' should probably be `char **' +``` ### Obfuscation The main obfuscation is the algorithm used to calculate square roots, sometimes known as the longhand method. The basic algorithm is itself obfuscated in that it only uses subtraction to calculate square roots. -(For a detailed explanation, check Google or see Jack Crenshaw's article -at http://www.embedded.com/98/9802fe2.htm) This program uses an even -more obscured version which includes the following: +For a detailed explanation, check Google or see Jack Crenshaw's article +at +. + +This program uses an even more obscured version which includes the following: - A single string is used to store two numbers of different lengths - Operations are done in a weird hybrid of base 10 and base 20 -- Subtraction is done addition style, i.e. 4 minus 8 equals 6 carry a -1 -- Recursive calls to main() +- Subtraction is done addition style, i.e. `4 - 8` equals `6` carry a `-1` +- Recursive calls to `main()` + +#### Minor obfuscations: -Minor obfuscations: - Self documenting whitespace in rectangular code block, for fun and glory (view with fixed-width font) - Integer constants adjusted to less meaningful values, just for added confusion - Hard-to-read, meaningless variable names to spite the reader -Challenges for the masses: -- What are the meanings [sic, plural] of the variable o? -- Why is (c+999)%10-(D[I]+92)%10 not equivalent to (c-D[I]+7)%10? +#### Challenges for the masses: + +- What are the meanings [sic, plural] of the variable `o`? +- Why is `(c+999)%10-(D[I]+92)%10` not equivalent to `(c-D[I]+7)%10`? - How does the program terminate? - Is the programmer sane? ;-) diff --git a/2001/cheong/cheong.c b/2001/cheong/cheong.c index dbd583fe6..97fef5f18 100644 --- a/2001/cheong/cheong.c +++ b/2001/cheong/cheong.c @@ -11,4 +11,4 @@ c=o+ (D[I]+82)%10-(I>l/2)* :!(o=pain(c/10,O,I-1))*((c+999 )%10-(D[I]+92)%10);}return o;} int main(int o,char **O) { -return O[1]?pain(o, O, l):1; } +return pain(o, O, l); } diff --git a/2001/coupard/.gitignore b/2001/coupard/.gitignore index 04b0c16d3..7e1830c99 100644 --- a/2001/coupard/.gitignore +++ b/2001/coupard/.gitignore @@ -1 +1,2 @@ coupard +test.wav diff --git a/2001/coupard/README.md b/2001/coupard/README.md index a98e88a97..a113e753c 100644 --- a/2001/coupard/README.md +++ b/2001/coupard/README.md @@ -1,11 +1,11 @@ # Most obfuscated sound - Pierre-Philippe Coupard - Lineo, Inc. - ATTN : Pierre-Philippe Coupard - 390 South 400 West - Lindon, UT 84042 - USA +Pierre-Philippe Coupard +Lineo, Inc. +ATTN : Pierre-Philippe Coupard +390 South 400 West +Lindon, UT 84042 +US ## To build: @@ -27,9 +27,13 @@ make ``` If you're using macOS then you won't have these devices. If however you install -sox from MacPorts or Homebrew you can do something like: +[sox](https://en.wikipedia.org/wiki/SoX) from +[MacPorts](https://www.macports.org) or [Homebrew](https://brew.sh) you can do +something like: - ./coupard | sox -q -traw -r8000 -b8 -e unsigned-integer - -tcoreaudio +```sh +./coupard | sox -q -traw -r8000 -b8 -e unsigned-integer - -tcoreaudio +``` Thanks go to [Yusuke Endoh](/winners.html#Yusuke_Endoh) for providing a proper command line (see [/2013/endoh3/README.md](2013/endoh3/README.md). @@ -45,41 +49,42 @@ your arm or the wall for confirmation. Past years' IOCCC entries do many marvellous things in small packages, such as console utilities, games, math, languages or even X applications. But they all have one thing in common (despite being hard -to read obviously) : when they interact with the user, they only +to read obviously): when they interact with the user, they only *display* things, i.e. they display either text or drawings. So, for a change, this program titillates the sense of hearing instead -of sight : this program is a self-contained speech synthesizer that +of sight: this program is a self-contained speech synthesizer that tells the current time through the computer's sound card - in just under 2 Kb of source code ! -In the 2001 IOCCC rules and guidelines documents, there is no mention of -what is or isn't acceptable regarding audio I/Os, but it is mentioned +In the 2001 IOCCC [rules](/2001/rules.txt) and +[guidelines](/2001/guidelines.txt) documents, there is no mention of +what is or isn't acceptable regarding audio I/O, but it is mentioned that hardware-specific and/or non-portable programs are not welcome. So, in order to do audio and satisfy those requirements, the format required -by /dev/audio has been chosen : /dev/audio is a rather ancient +by `/dev/audio` has been chosen: `/dev/audio` is a rather ancient fixed-format audio interface that is supported by the majority of Unices -that can do sound, as a lowest-denominator sound I/Os interface. +that can do sound, as a lowest-denominator sound I/O interface. -### Program usage: +### Program usage -* To listen to what the program says directly, invoke +To listen to what the program says directly, invoke ```sh ./coupard > /dev/audio ``` -the program then speaks out something like +The program then speaks out something like "The time is HH hours MM minutes SS seconds" in military time (24 hours). Of course, you need to have permissions -to write to /dev/audio, have your sound card enabled, the volume up, +to write to `/dev/audio`, have your sound card enabled, the volume up, the speakers connected ... :-) -* If you want to convert the audio output of the program into another -audio format, you can pipe it to sox for example (sox is the -Swiss army knife of Unix audio tools) : the command +If you want to convert the audio output of the program into another audio +format, you can pipe it to [sox](https://en.wikipedia.org/wiki/SoX) for example +(`sox` is the Swiss army knife of Unix audio tools): the command: ```sh ./coupard | sox -c1 -r8000 -tub - -c2 -r44100 -twav test.wav @@ -90,28 +95,30 @@ file and saves it into "test.wav". The output format of the program is 8KHz, unsigned 8-bit samples. -NOTE : the program's return code is meaningless +NOTE: the program's return code is meaningless. -### Audio quality: +### Audio quality The quality of the sound produced by the program is cross between a -yogurt-pot-and-string telephone and a bad gramophone, i.e. the S/N -ratio is very low and the signal's top frequency is very low as well. -This is because the audio is stored internally at a sampling rate of -4KHz (the Nyquist frequency is only 2KHz) with only 4-bit samples -(adding 24db of quantization noise to an already poor signal). +yogurt-pot-and-string telephone and a bad gramophone, i.e. the S/N ratio is very +low and the signal's top frequency is very low as well. This is because the +audio is stored internally at a sampling rate of 4KHz (the [Nyquist +frequency](https://en.wikipedia.org/wiki/Nyquist_frequency) is only 2KHz) with +only 4-bit samples (adding 24db of quantization noise to an already poor +signal). In short, you might have to listen twice to understand what the program is saying. 2048 bytes including the sound generation program doesn't leave much room for audio quality ;-) -### Speech generation: +### Speech generation Only 9 phonemes are used to generate the speech. Beside the limited number of words the program has to generate (66 words), the low sound quality is actually exploited to take liberties with certain consonants (for example, "s" and "f" sound very much the same at 4KHz, -so they can be merged into one phoneme). Because the psychoacoustic +so they can be merged into one phoneme). Because the +[psychoacoustic](https://en.wikipedia.org/wiki/Psychoacoustics) context around those phonemes is just sufficient, the words can be interpreted correctly most of the time despite the fact that they are pronounced quite wrongly. @@ -120,7 +127,7 @@ Internally, a table is used to generate most of the words, and composite words such as "thirty-five" are made up by the C code externally. -### Data compression: +### Data compression Even at 4KHz / 4 bits, the weight of all the phoneme samples and the word-to-phonemes table put together is over 1600 bytes, which is well @@ -134,22 +141,21 @@ decompression code can't be made small enough. The best compression compromise was found using a simple Huffman compressor, and encoding the compressed data by blocks of 13 bits in -pairs of printable ASCII characters : the raw data is compressed to +pairs of printable ASCII characters: the raw data is compressed to 8465 bits, and the resulting C string is therefore about 1300 characters, which leaves just enough room for the decompressor with a hard-coded Huffman tree, and the code that plays the phonemes in the right order. -### Note on compiler warnings and lint: +### Note on compiler warnings and lint -The program should build with gcc's -Wall -Werror and -ansi flags. If -the -pedantic flag is used, gcc will complain about the length of the -data string and the sign of its type, and also the fact that main() -returns with no value. The confusion with the sign of the char type -doesn't matter with the data string because it's composed only of -printable characters under 127. +The program should build with `gcc -Wall -Werror -ansi`. If the `-pedantic` +flag is used, gcc will complain about the length of the data string and the sign +of its type, and also the fact that `main()` returns with no value. The +confusion with the sign of the char type doesn't matter with the data string +because it's composed only of printable characters under 127. -When linting the program with lclint, it complains about a huge list +When linting the program with `lclint`, it complains about a huge list of things that, if corrected to make lint happy, would probably double the size of the source code. diff --git a/2001/ctk/README.md b/2001/ctk/README.md index 5b4643dc4..6cead0621 100644 --- a/2001/ctk/README.md +++ b/2001/ctk/README.md @@ -1,9 +1,9 @@ # Worst Driver - Chris King - 115 Foster Center Road - Foster, RI, 02825 - USA +Chris King +115 Foster Center Road +Foster, RI, 02825 +US ## To build: @@ -17,13 +17,9 @@ make ./ctk ``` -[Yusuke Endoh](/winners.html#Yusuke_Endoh) provided a patch to fix the ANSI -escape codes. It became apparent to [Cody Boone -Ferguson](/winners.html#Cody_Boone_Ferguson) (when he was looking at the source -code of this entry) that it was no longer valid ANSI escape sequences. He has -used them before (who hasn't ?) but that was a long time ago and with Yusuke's -patch it works. Cody notes that this fix will not just work for linux but macOS -too. Thank you Yusuke for your assistance! +The ANSI escape codes were no longer valid but [Yusuke +Endoh](/winners.html#Yusuke_Endoh) provided a patch to fix the ANSI escape +codes. This works with macOS as well. Thank you Yusuke! ## Try: @@ -32,7 +28,7 @@ too. Thank you Yusuke for your assistance! echo "Do or do not. There is no try." ``` -Make sure to hit 'q' to exit or else your terminal will be messed up (to restore +Make sure to hit `q` to exit or else your terminal will be messed up (to restore it you can try `stty sane` or `reset`). ## Judges' remarks: @@ -44,21 +40,23 @@ This is, of course, another of the retro games. ## Author's remarks: -This is a game based on an Apple ][ Print Shop Companion easter -egg named 'DRIVER', in which the goal is to drive as fast as +This is a game based on an Apple ][ Print Shop Companion [Easter +egg][1] named 'DRIVER', in which the goal is to drive as fast as you can down a long twisty highway without running off the -road. Use ',./', '[ ]', or 'bnm' to go left, straight, and -right respectively. Use '1234' to switch gears. 'q' quits. The +road. Use `,./`, `[ ]`, or `bnm` to go left, straight, and +right respectively. Use `1234` to switch gears. `q` quits. The faster you go and the thinner the road is, the more points you get. Most of the obfuscation is in the nonsensical if statements among other things. It works best on the Linux console: you get engine sound (!) and the * Lock keyboard lights tell you -what gear you're in (none lit=4th). The 'q' argument (no -leading '-') will silence the sound. It won't work on a terminal +what gear you're in (none lit=4th). The `q` argument (no +leading `-`) will silence the sound. It won't work on a terminal smaller than 80x24, but it works fine with more (try it in an XTerm with the "Unreadable" font and the window maximized vertically!). +[1]: https://en.wikipedia.org/wiki/Easter_egg_(media)#In_computing + ## Copyright and CC BY-SA 4.0 License: This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved. diff --git a/2001/dgbeards/.gitignore b/2001/dgbeards/.gitignore index 831f17e57..4fed522c0 100644 --- a/2001/dgbeards/.gitignore +++ b/2001/dgbeards/.gitignore @@ -1 +1,2 @@ dgbeards +dgbeards.alt diff --git a/2001/dgbeards/Makefile b/2001/dgbeards/Makefile index a1202606e..80b36b3a8 100644 --- a/2001/dgbeards/Makefile +++ b/2001/dgbeards/Makefile @@ -115,8 +115,8 @@ OBJ= ${PROG}.o DATA= TARGET= ${PROG} # -ALT_OBJ= -ALT_TARGET= +ALT_OBJ= ${PROG}.alt.o +ALT_TARGET= ${PROG}.alt ################# diff --git a/2001/dgbeards/README.md b/2001/dgbeards/README.md index 77a194238..68c964983 100644 --- a/2001/dgbeards/README.md +++ b/2001/dgbeards/README.md @@ -1,10 +1,10 @@ # Best AI - Doug Beardsley - Southern Adventist University - 359 Davis Rd. NW - Cleveland, TN 37312 - USA +Doug Beardsley +Southern Adventist University +359 Davis Rd. NW +Cleveland, TN 37312 +US ## To build: @@ -18,12 +18,31 @@ make ./dgbeards ``` -## Try: +### Alternate code: + +The author provided a way to speed it up a bit and also how to make it so it +doesn't crash on losing. [Cody Boone +Ferguson](/winners.html#Cody_Boone_Ferguson) made this alternate version with +the former change (the idea of crashing when losing is too good to fix in his +opinion). To compile: ```sh -echo "Do or do not. There is no try." +make alt ``` +Use `dgbeards.alt` as you would `dgbeards` above. Can you find a flaw in this +version that the author did not note? + + +## INABIAF - it's not a bug it's a feature! :-) + +This game crashes if it loses. + +## Try: + +See if you can figure out how to make the computer always lose. It's a very +simple thing to do. Read the author's remarks for clues. + ## Judges' remarks: This is probably the worst AI we've ever seen. So, then, why did @@ -35,16 +54,19 @@ Of particular interest is the author's decision that the program should crash if it loses. I've played chess with a lot of people like that, and I appreciate the realism. +BTW: if your goal is to lose and you do does that mean you win? :-) What does +winning mean in a game you're supposed to lose at? + ## Author's remarks: -FAQ: +### FAQ -Q: What does this program do? +#### Q: What does this program do? -A: It lets the user play two player or single player games of suicide -chess. Suicide Chess (also known as Losing Chess) is a variant of normal -chess. It is played on the same board and uses the same pieces. Here is -a list of the differences: +A: It lets the user play two player or single player games of [suicide +chess](https://en.wikipedia.org/wiki/Losing_chess). Suicide Chess (also known as +Losing Chess) is a variant of normal chess. It is played on the same board and +uses the same pieces. Here is a list of the differences: 1. The object of the game is to get to a position where you have no legal moves. This is usually accomplished by losing all of your pieces. @@ -66,36 +88,35 @@ can be captured. 5. Castling is not allowed. -Q: How do you use this program? +#### Q: How do you use this program? A: The program is fairly straightforward. When you start the program, it displays the opening position for a game of suicide chess and waits for user input. Commands are as follows: -quit - Quits the program -g - Causes the computer to make a move +- `quit` quits the program +- `g` causes the computer to make a move -Moves are represented by the long algebraic notation for the move. For -those not familiar with long algebraic notation, a move consists of a -square to move from followed by a square to move to. Squares are denoted -by a letter and a number. The letter specifies the column or file of the -square and the number specifies the row rank. Files are named from left -to right by the letters a-h. Rows are numbered from bottom to top with -the numbers 1-8. A sample move from the opening position is e2e3. This -means to move a piece from square e2 to e3. From the opening position, -this corresponds to moving the king pawn forward one square. This is -generally to be considered one of the best opening moves in suicide -chess. All moves, captures and otherwise, are represented with this -notation. A special case is pawn promotion moves. They use the same -notation followed by an '=' and a letter representing the piece to -promote to. The letters are R,N,B,Q,K representing rook, knight, bishop, -queen, and king respectively. The letters must be upper case. +Moves are represented by the long algebraic notation for the move. For those +not familiar with long algebraic notation, a move consists of a square to move +from followed by a square to move to. Squares are denoted by a letter and a +number. The letter specifies the column or file of the square and the number +specifies the row rank. Files are named from left to right by the letters `A` - +`H`. Rows are numbered from bottom to top with the numbers `1` - `8`. A sample +move from the opening position is `E2E3`. This means to move a piece from +square `E2` to `E3`. From the opening position, this corresponds to moving the +king pawn forward one square. This is generally to be considered one of the +best opening moves in suicide chess. All moves, captures and otherwise, are +represented with this notation. A special case is pawn promotion moves. They +use the same notation followed by an `=` and a letter representing the piece to +promote to. The letters are `R`, `N` , `B`, `Q`, `K` representing rook, knight, +bishop, queen, and king respectively. The letters must be upper case. You can also specify a command line argument of a single digit to change the search depth of the program. If no argument is specified, it defaults to a depth of 3. -Q: Are there any limitations in your program? +#### Q: Are there any limitations in your program? A: Yes. The first of the limitations is that you can only play legal moves according to the rules of suicide chess. En passant captures are @@ -108,37 +129,38 @@ losses several moves ahead, but does not announce the end of a game or the winner. Given the existing code it is easy to do this, but it was deemed unnecessary fluff. -Q: What is the playing strength of this program? +#### Q: What is the playing strength of this program? A: Playing strength is a relative term. Relative to other computer programs that play suicide chess, it is about the bottom. There is one -freeware program in existence called kenny that this program can beat, +freeware program in existence called `kenny` that this program can beat, but that is about it. Suicide chess is a very tactical game. Most humans who do not have any -experience in suicide chess will lose to this program. The Free Internet -Chess Server (http://www.freechess.org) is a free online chess server +experience in suicide chess will lose to this program. The [Free Internet +Chess Server](http://www.freechess.org) is a free online chess server that supports suicide chess. This server keeps track of ratings. The human ratings for suicide chess range from 1000 to about 2400. This program would probably be rated somewhere around 1700-1900. It is better than most players, but will get destroyed by experienced human opponents. -This program searches to a fixed depth of 3 ply. Because it does not +This program searches to a fixed depth of 3 +[ply](https://en.wikipedia.org/wiki/Ply_(game_theory)). Because it does not search very deep, it performs very poorly in quiet strategic positions. In such positions, it will often just shuffle pieces around aimlessly until a tactical exchange presents itself. A small amount of randomness has been added to make the program a more -interesting opponent. The to avoid a call to srand(), rand() and the -extra code for the required include files, the time() function is used as +interesting opponent. To avoid a call to `srand()`, `rand()` and the +extra code for the required include files, the `time()` function is used as the source of random data. It is a slow function, and since it is executed inside the search loop, there is a significant performance -decrease. To make it faster, replace the time() call with rand() and add -the line srand(time(0)); to the beginning of main(). I used the more -inefficient time() function to illustrate a different (and somewhat +decrease. To make it faster, replace the `time()` call with `rand()` and add +the line `srand(time(0));` to the beginning of `main()`. I used the more +inefficient `time()` function to illustrate a different (and somewhat obfuscated?) way of generating random numbers. -Q: Why is this program obfuscated? +#### Q: Why is this program obfuscated? A: Here are several reasons: @@ -168,7 +190,7 @@ penetrated by just preprocessing and beautifying the program. Fifth, various small obfuscations have been used in places all over the program. Short circuit evaluation is used as a substitute for if() statements in some places. The ternary operator is used. In the -author's opinion, use of the ternary operator is almost always a strong +author's opinion, use of the ternary operator is almost always a strong argument for employee turnover. Last, if you have succeeded in wading through the previous layers of @@ -177,36 +199,38 @@ implements is an obscure game. Casual inspection of the program might lead one to believe that it is an implementation of classic chess, but this is not so. -Q: What about the compiler warnings? +#### Q: What about the compiler warnings? -A: When compiled with gcc -Wall, the compiler generated the following +A: When compiled with `gcc -Wall`, the compiler generated the following warnings: +``` suggest parentheses around + or - in operand of & array subscript has type 'char' return type defaults to 'int' control reaches end of non-void function value computed is not used +``` -The "value computed is not used" warning happens because I use the && +The `value computed is not used` warning happens because I use the `&&` operator and take advantage of short circuit evaluation instead of using an if() statement. -The "suggest parentheses..." warnings are given because of expressions +The `suggest parentheses...` warnings are given because of expressions that depend on operator precedence details in the C language. Eliminating these warnings would reduce obfuscation. The other warnings are there because it would require more code to eliminate them and that can't be done given the size limit. -Q: Why does this program crash when it loses? +#### Q: Why does this program crash when it loses? A: What better way to admit defeat? The author thought this was appropriate sportsmanship for a program of this genre and can think of no worse job than trying to find an elusive bug in an intentionally obfuscated program. -[judge's note: This was followed by a description of the bug, and +[Judge's note: This was followed by a description of the bug, and the comment:] (Note, if this program wins, the author thinks it would be good to leave @@ -214,16 +238,11 @@ this information out of the remarks and encourage others to try and figure it out for themselves) [should you be too lazy to figure it out yourself, here's the author's -fix. I would have rot13'd it, but the punctuation would have survived.] +fix.] -begin 644 fix.txt -M5&AI&5D(&EN(&$@;G5M8F5R(&]F('=A>7,L(&)U -M="!T:&5R90II2!T:&%T(&%D9',@;VYL>2!O;F4@8GET92!T;R!T -M:&4@s?Y=G,e:s;` change +the `>` to a `>=` and the bug will be gone. ## Copyright and CC BY-SA 4.0 License: diff --git a/2001/dgbeards/dgbeards.alt.c b/2001/dgbeards/dgbeards.alt.c new file mode 100644 index 000000000..2b7cb4edf --- /dev/null +++ b/2001/dgbeards/dgbeards.alt.c @@ -0,0 +1,163 @@ +#include +#include +#include +#define A(x,y) i[a++]=(N){c,c+x,y}; +#define B(x,y) j[b++]=(N){c,c+x,y}; +#define C(j,k) for (j=0; j0)E; else A(_,0)_+=v; } +#define X(x) G(x,L) +#define Z(x,y) memcpy(x,y,256); + +typedef struct { +F a,b,c; +} N; + +F g[]="KSLAU", +p[256],v[]="{ ; } ; { ; ; ; { } ; { ; } { ; } { } ; { ; ; ; { ; } ; } } ; { ; ; { } ; { } } ; { ; ; { { ; ; { } } ; } ; ; { } ; { } } ; { ; ; { { ; { } } ; { ; ; { } ; { { ; ; { } ; ; ; ; { ; } { { ; ; ; { } ; { ; ; "; +F S[]="{}; ",W[256],L[1024]; +P q[]={-14,-31,-33,-18,14,31,33,18},r[]={-1,-17,-16,-15,1,17,16,15},_,a,b,c,d,e,t=1,x,y,z; +N i[500],j[500],*k,u; +P f(N *V) { + a=b=0; + C(d,8) + C(e,8) + c=d<<4|e; + if(p[c]==0||p[c]*t<0)continue; + switch(p[c]<0?-p[c]:p[c]){ + K 80: + if(56+t*40==(c&112)&&!p[c-32*t]) + A(t*-32,0) + if(56+t*-40==(c&112)){ + if(!(c-17*t&136)&&p[c-17*t]*t<0){ + C(_,5) + B(-17*t,(g[_]^_)*t)} + } + if(!(c-15*t&136)&&p[c-15*t]*t<0){ + C(_,5) + B(-15*t,(g[_]^_)*t)} + } + C(_,5) + A(t*-16,(g[_]^_)*t)} + }else{ + if(!p[c-16*t]) + A(t*-16,0) + if(!(c-(17*t)&136)&&p[c-17*t]*t<0){ + B(-17*t,0) + } + if(!(c-(15*t)&136)&&p[c-15*t]*t<0){ + B(-15*t,0) + } + } + E; + K 78:D(q)E; + K 81: + K 66:O(17)O(-17)O(15)O(-15) + if(p[c]==66||p[c]==-66) + E; + K 82:O(1)O(-1)O(16)O(-16)E; + K 75:D(r) + } ; + } + } + if ( b > 0 ) { + C(_,b)V[_]=j[_]; } + R b; + } else { + C(_,a)V[_]=i[_]; } + R a; + } +} +F *G(F *n, F *o){ + a=b=0; + for(; n[b]; d=0){ + do{ + d*=4; + d+=W[n[b++]]; + } while(++b<8*a+8); + o[a++]=d; + } + o[a]=0; + R o; +} +m(N a){ p[a.b]=a.c?a.c:p[a.a]; p[a.a]=0; } +h(){ + J X("{ ; { { { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { { ; ; ")); + c=0; C(c,120)c%8==0&&putchar(56-c/16); + if(p[c]<0){ + J X("} { { ; { { { ; ; ; { ; } } } ; { "),-p[c]); + } else if(p[c]>0) + J X("} { { ; { { { ; } } } ; { { ; { { "),p[c]); + else + J"| "); + c%8==7?J X("} { { { ; ; { ; { { { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { { ; ; ")),c+=8:0; + } +} +s() { + b=0; C(a,256) + if(v[b]==94){ + b++; C(c,v[b]-32)p[a++]=v[b+1]-120;} + b+=2; a--; + } else + p[a]=v[b++]-120; + } +} +P w() { + P v=0; + C(_,120) + p[_]&&(p[_]*t>0&&v--,p[_]*t<0&&v++); + } + v+=f(i); v-=b?100:0;t=-t; v-=f(i); v+=b?100:0;t=-t; + + R v; +} +P V(P n, P o) { + P s=-I,G,H,Y; + N M[500]; + F u[256]; + + if(!(n+o))R w()+rand()%9-4; + if(!(H=f(M)))R I; + H<5?H==1?n++:(o<6?o++:0):0; + Z(u,p) + C(G,H) + Z(p,u) + m(M[G]); + t=-t; + s=(e=-V(n-1,o))>s?Y=G,e:s; + t=-t; + } + e=Y; + R s; +} +main(P db, F *bd[]){ + srand(0); + N o[500]; + F T[256]; + + C(a,256)W[a]=-1; } + C(a,4)W[S[a]]=a; } + G(v,v); s(); + while(1){ + h(); + b=f(o); + scanf("%s",L); + if(strcmp(L,"quit")==0)R 0; + else if(strcmp(L,"g")==0){ + Z(T,p) + J G("} } } ; } ; { } } ; { } } } } ; } } { ; { { { ; } } } ; } { { { ; ; ",L), V(db>1?atoi(bd[1]):3,0)); + Z(p,T)m(o[e]); t=-t; + }else{ + u.a=896-16*L[1]; + u.b=896-16*L[3]; + u.a+=L[0]-97; + u.b+=L[2]-97; + u.c=L[4]?L[5]:0; + C(a,b) + if(u.a==o[a].a&&u.b==o[a].b&&u.c==o[a].c)E; + } + a==b?J X("} { ; } } ; { } ; { } ; } } } ; } } ; { } } ; { { ; { { } ; } } ; } } ; } ; } } { { ; ; ")):(m(u),t=-t); + } + } +} diff --git a/2001/herrmann1/.gitignore b/2001/herrmann1/.gitignore index 957e2a9b9..fced10ad5 100644 --- a/2001/herrmann1/.gitignore +++ b/2001/herrmann1/.gitignore @@ -1 +1,4 @@ herrmann1 +error +herrmann1-1.c +herrmann1-3.c diff --git a/2001/herrmann1/README.md b/2001/herrmann1/README.md index c39292628..9ea366d35 100644 --- a/2001/herrmann1/README.md +++ b/2001/herrmann1/README.md @@ -1,13 +1,9 @@ # Best abuse of the C preprocessor - Immanuel Herrmann - University of Freiburg, Germany - Rehlingstr. 17 - 79100 Freiburg - Germany - - http://pcpool.mathematik.uni-freiburg.de/~immi/ - +Immanuel Herrmann +Germany + + ## To build: ```sh @@ -17,9 +13,16 @@ make ## To run: ```sh -./herrmann1.sh 'prg=file' + ./herrmann1.sh 'prg=file' ``` +NOTE: this entry seems to rely on older versions of gcc for the compilation +stage and as such if you wish to see that part like it was designed you will +need an older compiler perhaps gcc 2.95. + +NOTE: some files are missing and are not found in the archive either. See +[bugs.md](/bugs.md) for more details. + ## Try: ```sh @@ -65,7 +68,7 @@ be reported nicely. (That's something which is not often seen in IOCCC programs.) - Ultra-fast: The resulting C program will print the output in -time O(n), where n is the length of the output. This means for +time `O(n)`, where `n` is the length of the output. This means for example that you can solve NP hard problems in polynomial time! ;-) @@ -75,10 +78,9 @@ terminal! ### How to use it -For the impatient ------------------ +#### For the impatient -The info files "herrmann1.turing" and "herrmann1.gcd" are sample +The info files `herrmann1.turing` and [herrmann1.gcd](herrmann1.gcd) are sample programs for the Turing machine. For example, type ```sh @@ -88,6 +90,7 @@ programs for the Turing machine. For example, type and watch the animated Turing machine multiply 8 by two (in unary representation). Here's a screen shot during compilation: +``` /* * * State: st2. @@ -98,58 +101,66 @@ unary representation). Here's a screen shot during compilation: * * */ +``` (As on real videos, you'll see a bit of "white noise" at the beginning and at the end.;-) After compilation has terminated, -type ./prog to see the final result. The output will be +type `./herrmann1` to see the final result. The output will be Final tape: +``` * ..OOIIIIIIIIIIIIIIIIOOOO.. * +``` (Note that the last frame of the animation is _not_ the final result.) In the previous example, the Turing machine started on the default -tape of the program "times2.turing". To provide your own tape, type +tape of the program `times2.turing`. To provide your own tape, type (for example) -./build prg=times2.turing tape="O O O I I I O O O" +```sh +./herrmann1 prg=times2.turing tape="O O O I I I O O O" -(The O's and I's are letters, not digits.) You might prefer to +``` + +(The `O`s and `I`s are letters, not digits.) You might prefer to provide only a finite portion of the tape, like I did above. In -this case, the remainder of the tape is filled with O's. ;-) +this case, the remainder of the tape is filled with `O`s. ;-) If you just type: ``` -./build +./herrmann1 ``` and run the program, you'll get a usage message (and the return code will be 2). Note: To get a really nice animation, you'll need a terminal which -is able to scroll fast enough. (xterm is not very good. The -kde terminal "konsole" or the text console under linux are much -better. Simply try some out.) +is able to scroll fast enough. `xterm` is not very good. The +KDE terminal `konsole` or the text console under linux are much +better. Simply try some out. ### Writing your own programs Now, let's assume you want to write a program which adds 1 to a number in unary representation. (That is, a row of I's is expected, and one more I is appended to the row.) Let's call it -"plus1.turing". Here's what it could look like: +`plus1.turing`. Here's what it could look like: +```c /* Search beginning of number. */ #define start_O O, right, start /* Number found. Move one step to the left. */ #define start_I I, left, st2 /* Write a I and stop */ #define st2_O I, left, stop +``` Some explanations: - The tape alphabet is always O and I. @@ -174,7 +185,9 @@ O's). For many programs, this doesn't make much sense (as is the case for "plus1.turing"). So you might want to provide a default tape by adding a line like +```c #define tape O O O O O I I I I +``` to your program. @@ -184,11 +197,15 @@ When writing long programs, the most common errors are to forget to define a state or to misspell one. Let's assume you forgot the line +```c #define start_I I, left, st2 +``` Remove it and type +```sh ./herrmann1 'prg=plus1.turing' +``` The output will be @@ -196,17 +213,19 @@ Undefined state start. Tape: +``` * ..OOOOOOOOIIIIOO.. * +``` and the return code will be 1. As you can see, the Turing machine -moved over the O's, but when it arrived at the I (still in state +moved over the O's, but when it arrived at the `I` (still in state start), the error occurred. Note that other kinds of errors can cause compilation to fail. If this happens, the build script will write the error message of -gcc into a file called "error" and then exit. +gcc into a file called `error` and then exit. ### What the build script does @@ -223,28 +242,28 @@ picture won't look right. And second, after some time, the file will grow too big for your hard disk. (The amount of white space grows exponentially.) So after each preprocessing, the first thing the build script does is remove all the unnecessary white space -using sed. +using `sed`. -(gcc would even insert #line directives if I didn't suppress -them with the -P option.) +(gcc would even insert `#line` directives if I didn't suppress +them with the `-P` option.) ### Some more details - The arguments passed to the build script are passed on to gcc -with a "-D" before. I had a slight technical problem doing this +with a `-D` before. I had a slight technical problem doing this (especially with the spaces that can appear within the tape argument). That made the build script a bit longer. - It would be enough to pass the defines in the first preprocessing. The program then "remembers" them. However, it -doesn't matter if they are passed in all preprocessings. (This +doesn't matter if they are passed in all pre-processes. (This doesn't sound very impressive, but it has required some extra lines of code.) -- During the preprocessing, intermediate files "herrmann1-1.c" and -"herrmann1-2.c" are generated. +- During the preprocessing, intermediate files `herrmann1-1.c` and +`herrmann1-2.c` are generated. -- Also, a file "error" is generated. This file is removed after +- Also, a file `error` is generated. This file is removed after the compilation, except if gcc produced an error; then it contains the error message. (I can't let gcc output all its messages directly, because the warnings would clobber the animation. I @@ -256,7 +275,7 @@ of an error, but I didn't want to make it yet longer.) - The program is compressed. In the first three preprocessing passes, it uncompresses itself and initializes the "variables". So if you want to understand how it works, the best -thing is to preprocess it three times and then look at it +thing is to pre-process it three times and then look at it again. (However, I wouldn't have wasted three passes if they weren't needed anyway to initialize the tape in certain cases. Find out why.) @@ -270,16 +289,16 @@ easy. - The next problem to solve was how to pass results of a calculation of one preprocessing to the next one. This is done -by outputting #defines with the result. But there's a problem -with this: it is impossible to output a "#define result xxx", -where xxx depends on the previous value of result. Try it if you +by outputting `#define`s with the result. But there's a problem +with this: it is impossible to output a `#define result xxx`, +where `xxx` depends on the previous value of result. Try it if you don't believe it. And find out what I did instead. - What's a useful way to store information, especially the content -of the tape? Of course, a "#define tape OOIOOIOIIIIO" contains +of the tape? Of course, a `#define tape OOIOOIOIIIIO` contains the information, but then, how do you access the information? (For example, you won't be able to write preprocessor code which -replaces the first O by I.) My answer looks very much like the +replaces the first `O` by `I`.) My answer looks very much like the way a stack would have been implemented in lambda calculus. (The tape is implemented as two stacks, to be exact.) And still, there were some technical problems to solve. Look at the program @@ -289,17 +308,17 @@ for more details. to access the information in the user-provided program, the way a non-defined state is detected, the way the picture is produced, etc. If you want a real challenge, try to understand -what the line "w j k(P ## x)" does. +what the line `w j k(P ## x)` does. - Due to the fact that our alphabet has only 53 ;-) letters, I had to use many variables more than once. - I couldn't refrain from doing a little bit of nasty stuff like -#define a 0&0 -#if !a + #define a 0&0 + #if !a -Of course, it is a bit more subtle, and even useful. + Of course, it is a bit more subtle, and even useful. - The layout of the source code..., well, let's call it the "modern art of programming" - a mixture of program-like @@ -312,11 +331,11 @@ indenting and modern art. There are even some comments... of gcc produced "internal compiler errors" (obviously not my fault). -- The only warnings I get tell me that I'm undefining __FILE__ and +- The only warnings I get tell me that I'm undefining `__FILE__` and that preprocessing directives are not recognized within macro args. My answer to this is "yes, I know this and it's all -right". With "-Wall", I also get some warnings about "/*" -inside comments (Well, _I_ like some well-placed "/*/*/".) as +right". With `-Wall`, I also get some warnings about `/*` +inside comments (Well, _I_ like some well-placed `/*/*/`.) as well as some suggestions where to place some more parentheses (as if I didn't know the operator precedence). @@ -333,31 +352,31 @@ script, so that one does not have to choose "preprocess" from the menu over and over again. I leave this as an exercise to the experienced Mac programmer.) -- In the build script, I passed the -P option to gcc to suppress -the insertion of #line directives. If your compiler doesn't -support this option (and does insert #line directives), you -should change the call to sed to remove them, too: Add +- In the build script, I passed the `-P` option to gcc to suppress +the insertion of `#line` directives. If your compiler doesn't +support this option (and does insert `#line` directives), you +should change the call to `sed` to remove them, too: Add --e "/^#line/ d" + -e "/^#line/ d" -to the sed parameters. Or, if your #line directives look like + to the sed parameters. Or, if your `#line` directives look like -# 15 "filename" + # 15 "filename" -add + add --e "/^# [0-9]/ d" + -e "/^# [0-9]/ d" -instead. + instead. -- First, I had "-ansi -pedantic" turned on, but on some systems, -the stdio.h is not compatible to that, so I turned it back off. +- First, I had `-ansi -pedantic` turned on, but on some systems, +the `stdio.h` is not compatible to that, so I turned it back off. - The build script probably needs a bash to run in. So perhaps you -have to add "#!/bin/bash" or something like this at the +have to add `#!/bin/bash` or something like this at the beginning. -- On SunOS, I had to remove the "-q" option from diff in the build +- On SunOS, I had to remove the `-q` option from diff in the build script. ## Copyright and CC BY-SA 4.0 License: diff --git a/2001/herrmann1/plus1.turing b/2001/herrmann1/plus1.turing new file mode 100644 index 000000000..152880d52 --- /dev/null +++ b/2001/herrmann1/plus1.turing @@ -0,0 +1,7 @@ +/* Search beginning of number. */ +#define start_O O, right, start +/* Number found. Move one step to the left. */ +#define start_I I, left, st2 +/* Write a I and stop */ +#define st2_O I, left, stop + diff --git a/2001/herrmann2/.gitignore b/2001/herrmann2/.gitignore index 24be698bf..8c2df18c0 100644 --- a/2001/herrmann2/.gitignore +++ b/2001/herrmann2/.gitignore @@ -1 +1,2 @@ herrmann2 +herrmann2.alt diff --git a/2001/herrmann2/Makefile b/2001/herrmann2/Makefile index 61271d1e6..efde9295a 100644 --- a/2001/herrmann2/Makefile +++ b/2001/herrmann2/Makefile @@ -114,8 +114,8 @@ OBJ= ${PROG}.o DATA= herrmann2.cup herrmann2.ioccc TARGET= ${PROG} # -ALT_OBJ= -ALT_TARGET= +ALT_OBJ= ${PROG}.alt.o +ALT_TARGET= ${PROG}.alt ################# @@ -130,13 +130,16 @@ all: data ${TARGET} supernova deep_magic magic charon pluto ${PROG}: ${PROG}.c - ${CC} ${CFLAGS} $< -o $@ ${LIBS} + ${CC} ${CFLAGS} -m32 $< -o $@ ${LIBS} # alternative executable # alt: data ${ALT_TARGET} @${TRUE} +${ALT_TARGET}: herrmann2.c + ${CC} ${CFLAGS} $< -o $@ ${LIBS} + # data files # data: ${DATA} diff --git a/2001/herrmann2/README.md b/2001/herrmann2/README.md index 1c68e387e..577397f32 100644 --- a/2001/herrmann2/README.md +++ b/2001/herrmann2/README.md @@ -1,12 +1,11 @@ # Most eye-crossing - Immanuel Herrmann - University of Freiburg, Germany - Rehlingstr. 17 - 79100 Freiburg - Germany - - http://pcpool.mathematik.uni-freiburg.de/~immi/ +Immanuel Herrmann +University of Freiburg, Germany +Rehlingstr. 17 +79100 Freiburg +Germany + ## To build: @@ -17,7 +16,10 @@ make [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed this to work with clang by changing the args to main() to be `int` and `char **` respectively and changing specific references to the `argv` arg, casting to int which was its old -type. Thank you Cody for your assistance! +type. However this entry only works completely if compiled as 32-bit (it does +work in part if compiled as 64-bit). See the alternate code below for +information on the 64-bit version and [bugs.md](/bugs.md) for more details on +this issue in general. Thank you Cody for your assistance! ## To run: @@ -26,12 +28,18 @@ type. Thank you Cody for your assistance! ./herrmann2 ``` -Cody notes that [Yusuke Endoh](/winners.html#Yusuke_Endoh) does not get a -segfault with some of the invocations (without fixing it for clang) but Cody -does get a segfault both before fixing it for clang and after. Yusuke provides -some interesting thoughts which can be found -[here](https://mame-github-io.translate.goog/ioccc-ja-spoilers/2001/herrmann2.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=en-US&_x_tr_pto=wapp). -Thank you Yusuke for your interesting thoughts! + +### Alternate code: + +As noted above an alternate version is available for 64-bit. This will crash in +some of the invocations given by the author but it will work for the basic +operations. To use try: + +```sh +make alt +``` + +Use `herrmann2.alt` as you would `herrmann2` above and below. ## Try: @@ -45,26 +53,33 @@ Try running each command a few times and notice the different output. Can you figure out why each is different? -If you use vi(m) you can see a pattern in `hermmann2.cup` and `herrmann2.ioccc` -by say: +If you use vi(m) you can see a pattern in [herrmann2.cup](herrmann2.cup) and +[herrmann2.ioccc][(herrmann2.ioccc]) by say: - /[pon] +``` +/[pon] +``` and - /l +``` +/l +``` -For additional fun in `herrman2.cup` try: +For additional fun in [herrmann2.cup](herrmann2.cup) try: - /[po] - /q +``` +/[po] +/q +``` -and in `herrmann2.ioccc` try: - - /n +and in [herrmann2.ioccc](herrmann2.ioccc) try: +``` +/n +``` ## Judges' remarks: @@ -87,12 +102,12 @@ yes, the program itself is such a 3D picture. 1. Create a file which describes the desired 3D picture. The file must be a block of lowercase letters the size of the desired picture. The letters specify the depth of the corresponding pixel: -"a" means close to the paper, "z" means far away. The info files +`a` means close to the paper, `z` means far away. The info files are examples. Be aware that the size of the picture is restricted to about 9k. 2. Pipe your picture into the program. The output will be your -3D picture, constructed of random characters (with ascii code between +3D picture, constructed of random characters (with ASCII code between 32 and 126). For example, type ```sh @@ -107,8 +122,8 @@ argument. When it arrives at the end of the argument, it will start over at the beginning. Example: ```sh -./herrmann2 "234 84 045 5 6765 7487 65190 84 656 254 12 43931 818 0 6542\ -341 45 567 76967 7244 606 976567 895 81898 095 68678 1843 4650547\ +./herrmann2 "234 84 045 5 6765 7487 65190 84 656 254 12 43931 818 0 6542 \ +341 45 567 76967 7244 606 976567 895 81898 095 68678 1843 4650547 \ 565980691 389 04974" < herrmann2.ioccc ``` @@ -174,7 +189,7 @@ only a sixth of the characters can be chosen freely! (457 of 1840, to be exact.) In contrast, in palindrome programs, for example, half of the characters can be chosen freely. -- I did not cheat by using comments or -D options - something +- I did not cheat by using comments or `-D` options - something I've seen even some palindrome programs do. In fact, at my first attempt at writing the program I became convinced that it isn't possible without cheating. But then I found out that with @@ -195,7 +210,7 @@ one). Which is the other digit I could have put there instead, and what other changes to the program would have been necessary? Without violating the constraints of course.) -- The fact that the main loop of the program calls "main" +- The fact that the main loop of the program calls `main` recursively is nothing new. New however is that this program only needs a logarithmic recursion depth! (Find out how this works.) @@ -213,10 +228,10 @@ and let the result inspire you. ;-) - I fear that gcc is the only compiler for which this program works. Due to the severe restrictions, I was forced to use declarations of int variables, functions and parameters without -specifying their type. The biggest problem was to put "int -main(int c, char ** v){" into the program. After some time, I +specifying their type. The biggest problem was to put `int +main(int c, char ** v){` into the program. After some time, I became convinced that this is impossible. Finally, at least I -managed to squeeze "main(c, v){" into the constraints instead. +managed to squeeze `main(c, v){` into the constraints instead. - Also, a lot of warnings are produced - most of them "data definition has no type or storage class", but also some @@ -228,12 +243,12 @@ get rid of them. versions of gcc. I tested it with versions 2.7.2.1, 2.8.1, 2.95.2, and ecgs-2.91.66. -- Of course I couldn't put "#include"-lines at the beginning of +- Of course I couldn't put `#include`s at the beginning of the program. Usually, this is not really necessary with gcc. However, for this program it would have been, because some functions appear as function pointers, and as such they are not -generated implicitly. So the build script has to pass "-include -..." to gcc. A problem with this is that the complete path of +generated implicitly. So the build script has to pass `-include +...` to gcc. A problem with this is that the complete path of the include files has to be provided. In the build script, I assume that the path is /usr/include, but this can easily be adapted. diff --git a/2001/jason/README.md b/2001/jason/README.md index e6f5d2687..fb3b324c8 100644 --- a/2001/jason/README.md +++ b/2001/jason/README.md @@ -1,11 +1,10 @@ # Best Of Show - Jason Orendorff - 5 Buchanan St. - Nashua, NH 03060 - USA - - http://www.jorendorff.com/ +Jason Orendorff +5 Buchanan St. +Nashua, NH 03060 +US + ## To build: @@ -44,27 +43,30 @@ Of particular interest: Go ahead, run it through the preprocessor. You TED Shroyer came up with the idea that made it possible to hide all the text. Thanks, TED. You won. :) - -$ cc -o prog prog.c -$ ./prog +```sh +$ cc -o jason jason.c +$ ./jason you are in a maze of twisty little passages caves lead: left forward back you see a lamp > _ +``` + This program is a rather nostalgic little labyrinth game. Start -out by typing "get lamp", then use the direction words "left", -"right", "forward", and "back" to explore the caves. Note that +out by typing "`get lamp`", then use the direction words "`left`", +"`right`", "`forward`", and "`back`" to explore the caves. Note that these words can refer to different passages depending on which way -you're facing. "back" always takes you back the way you came. +you're facing. "`back`" always takes you back the way you came. Type "quit" to quit. The maze is randomly generated each time you play. The algorithm ensures that you start at least 6 hops away from the exit. All passages are two-way. -(There is a trick, well-known among adventure game fans, to +(There is a trick, well-known among +[Adventure](https://en.wikipedia.org/wiki/Colossal_Cave_Adventure) game fans, to keeping one's bearings in games like this. Unless you know the trick, it can be very difficult to find your way around. Try it out first; I'll give away the secret at the bottom of this @@ -79,10 +81,10 @@ points per item, and bonus points for speed. Why I think this program is obfuscated: -* 70% more # symbols than the average entry. +* 70% more `#` symbols than the average entry. * Where are all the messages? The game is downright chatty for - only having two string literals ("%d \n" and "Y\n : ! ,.?>"). + only having two string literals (`"%d \n"` and `"Y\n : ! ,.?>"`). * There is exactly one loop in the program, a for loop, and it is clearly the product of a deranged mind. Running the @@ -98,13 +100,13 @@ Why I think this program is obfuscated: * Attempts to replace the one-character identifiers with longer, more meaningful names will likewise cause problems. In fact, - simply changing all the Y's to Z's and vice versa results in + simply changing all the `Y`s to `Z`s and vice versa results in some unexpected side effects. When all warnings are enabled, some compilers express the desire to see a few more parentheses. I respectfully submit that there are plenty of parentheses in the program (370 in all.) Besides, any -more would put me over the size limit. gcc also generates a +more would put me over the size limit. `gcc` also generates a warning about some calculations not being used. Having just spent 19 hours staring at this program, sweating over every character, I swear gcc is wrong. @@ -114,8 +116,10 @@ I find the plaintive chorus "B? B?" particularly poignant. Also, smiley faces are formatted flush left. (If you don't find the game entertaining, see if you can find +``` the fish scales Q)++j< the shooting star -~- ~ -~i + +``` in the source code.) @@ -125,9 +129,11 @@ in the source code.) -[GAME STRATEGY SPOILER: The trick, of course, is to drop items in -empty rooms to mark them. That way you usually know if you're in a -room you've seen before. It greatly aids mapping.] +### GAME STRATEGY SPOILER + +The trick, of course, is to drop items in empty rooms to mark them. That way +you usually know if you're in a room you've seen before. It greatly aids +mapping. ## Copyright and CC BY-SA 4.0 License: diff --git a/2001/kev/README.md b/2001/kev/README.md index 96b917b35..3e95bab9c 100644 --- a/2001/kev/README.md +++ b/2001/kev/README.md @@ -1,12 +1,12 @@ # Best Curses Game - Kevin Pulo - School of Information Technologies - Madsen Building F09 - University of Sydney, NSW, 2006 - Australia - - http://www.kev.pulo.com.au/ +Kevin Pulo +School of Information Technologies +Madsen Building F09 +University of Sydney, NSW, 2006 +Australia + +Mastodon: ## To build: @@ -38,12 +38,8 @@ box. ## Author's remarks: - NETWORK P*NG! - [=================] - - Kevin Pulo - kev@pulo.com.au +**NETWORK PONG!** ### REQUIREMENTS @@ -53,35 +49,34 @@ box. ### DESCRIPTION -This program is a two-player networked version of the eighties -arcade classic, "pong". It uses standard TCP sockets to -communicate over the net, and ncurses for display. It supports -variable terminal sizes (though both players must have the same -terminal size) and game speeds. Each player has a paddle to hit -the ball, and you get points for getting the ball past your -opponent's paddle. It's pretty fun! :) +This program is a two-player networked version of the eighties arcade classic, +[Pong](https://en.wikipedia.org/wiki/Pong). It uses standard TCP sockets to +communicate over the net, and `ncurses` for display. It supports variable +terminal sizes (though both players must have the same terminal size) and game +speeds. Each player has a paddle to hit the ball, and you get points for +getting the ball past your opponent's paddle. It's pretty fun! :) ### RUNNING -Run the server first without any command line arguments, ie. +Run the server first without any command line arguments, i.e. ```sh ./kev ``` Then run the client with a single command line argument which is -the name of the machine running the server, eg. +the name of the machine running the server, e.g. ```sh ./kev localhost ``` -Make sure that the terminals on both ends are the same size. -Also, the TCP port number specified in the build file mustn't be -blocked by a firewall. +Make sure that the terminals on both ends are the same size. Also, the TCP port +number (5455) specified in the [Makefile](Makefile) mustn't be blocked by a +firewall. Here's a good quick example to see it in action on your own -machine, assuming you have Xwindows: +machine, assuming you have `Xwindows`: ```sh xterm -geometry 80x40 -fg green -bg black -fn 9x15bold -e ./kev & @@ -91,9 +86,9 @@ xterm -geometry 80x40 -fg green -bg black -fn 9x15bold -e ./kev localhost& ### PLAYING Your paddle is the one at the bottom of the screen, your opponent -is at the top. To move your paddle left, hold down ',' (ie. '<' -but don't press shift). To move your paddle right, hold down '.'. -To quit, either player may press 'q'. +is at the top. To move your paddle left, hold down `,` (i.e. `<` +but don't press shift). To move your paddle right, hold down `.`. +To quit, either player may press `q`. The current score is shown on the left side of the halfway line. Your score is the lower number, your opponents score is the upper @@ -110,10 +105,10 @@ will decrease (or if the ball is going slowly enough, it'll turn around). You might want to increase your keyboard repeat rate before -playing. On the Linux console try "kbdrate -r 24.0 -d 250" -(kbdrate might be "hidden" from normal users in /sbin, and you -might need to be root anyway), in Xwindows try "xset r rate 250 -24" (find out your current rate first with "xset q", so that you +playing. On the Linux console try `kbdrate -r 24.0 -d 250` +(`kbdrate` might be "hidden" from normal users in `/sbin`, and you +might need to be root anyway), in `Xwindows` try `xset r rate 250 +24` (find out your current rate first with `xset q`, so that you can reset it later). Look below in the Building section for info on how to speed up or @@ -122,23 +117,23 @@ terminal size). ### BUILDING -Just run the Makefile as above. The "SPEED" variable in the Makefile -controls the speed of the game (defaults to 50). This speed is +Just run `make`to use the Makefile as above. The `SPEED` variable in the Makefile +controls the speed of the game (defaults to `50`). This speed is the delay between frames in milliseconds. Thus a value of 0 will make the game go as fast as your network can handle, and values less than 50 are useful for larger terminals or more exciting games. The program needs bandwidth equal to 1/s bytes per second -(where "s" is the speed value). Any latency on the network will -be added to s - so you should probably subtract any latency from -the value of s you want to have. Given that loopback and fast +(where `s` is the speed value). Any latency on the network will +be added to `s` - so you should probably subtract any latency from +the value of `s` you want to have. Given that `loopback` and fast Ethernet LANs are both much less than 1ms of latency, you should only need to worry about this if you plan on playing over a slower -link like a cable modem, DSL, or (God-forbid) dialup. +link like a cable modem, DSL, or (God-forbid) dial-up. The TCP port to use for network communications is specified by the -"PORT" variable in the Makefile. If the default of 5455 is +`PORT` variable in the Makefile. If the default of `5455` is blocked for whatever reason, you can change it to something else. -Of course if you use a port < 1024, you'll need to be root. +Of course if you use a `port < 1024`, you'll need to be root. ### OBFUSCATION @@ -159,22 +154,22 @@ unexpectedly cool. :) ### BUGS -There are 3 warnings when I compile with gcc 2.95.3 (-Wall -ansi --pedantic) on my Linux system, but all are completely harmless. +There are 3 warnings when I compile with gcc 2.95.3 (`-Wall -ansi +-pedantic`) on my Linux system, but all are completely harmless. I don't like the curses and/or termcaps/terminfos on IRIX and Solaris (the only two non-Linux systems I have access to). -Despite calling timeout(0), notimeout(win, TRUE), nodelay(win, -TRUE) and/or keypad(win, FALSE), it still seems to force a delay -into calls to getch() - I'm guessing at a termcap/terminfo level. +Despite calling `timeout(0);`, `notimeout(win, TRUE);`, `nodelay(win, +TRUE);` and/or `keypad(win, FALSE);`, it still seems to force a delay +into calls to `getch()` - I'm guessing at a termcap/terminfo level. At any rate, I can't seem to force no delay. This is a shame, because it basically plays havoc with the input code, particularly the read-ahead canceller. It still works, but not nearly as well -(keypresses are dodgey and holding down keys doesn't always work), -and so I _much_ prefer and recommend Linux libncurses. +(key presses are dodgy and holding down keys doesn't always work), +and so I _much_ prefer and recommend Linux `libncurses`. -Sometimes when 'q' is pressed in one, the other will crash out -with "Broken pipe". +Sometimes when `q` is pressed in one, the other will crash out +with `Broken pipe`. If the specified port can't be bound or connected to, the program segfaults. @@ -185,7 +180,7 @@ possible to crash the program a player scores over a billion points (1e9). Maybe you can consider that the goal... ;) If you run the client and server on different architectures, both -architectures need to have the same character systems (ie. don't +architectures need to have the same character systems (i.e. don't try mixing ASCII and EBCDIC). It is independent of endianness though. diff --git a/2001/ollinger/README.md b/2001/ollinger/README.md index bee457161..d763ff02a 100644 --- a/2001/ollinger/README.md +++ b/2001/ollinger/README.md @@ -1,13 +1,8 @@ # Best primal ASCII graphics - Nicolas Ollinger - Ecole Normale Superieure de Lyon - LIP, ENS Lyon - 46, allée d'Italie - 69364 Lyon Cedex 07 - France - - http://www.ens-lyon.fr/~nollinge/ +Nicolas Ollinger +France + ## To build: @@ -21,6 +16,10 @@ make ./ollinger integer ``` +### INABIAF - it's not a bug it's a feature! :-) + +This program will very likely crash or do something else without an arg. + ## Try: ```sh @@ -28,7 +27,7 @@ make ``` Try the above command in a large window, say 200 chars wide and 100 -high (200x100) with a tiny font, +high (200x100) with a tiny font. ## Judges' remarks: @@ -39,19 +38,20 @@ Do get lost in the programs line of thought! :-) ### What's this? What do you see? On the left, you will see an enumeration of all successive -primes from 2 to the parameter you gave to the program. On the right part, -you can see the sieve used to find these primes. The big diagonals from -right to left are used to erase composed numbers. When no diagonal crosses -a number, then the left cell take value 1 and the number is prime. +[primes](https://en.wikipedia.org/wiki/Prime_number) from 2 to the parameter you +gave to the program. On the right part, you can see the sieve used to find these +primes. The big diagonals from right to left are used to erase composed numbers. +When no diagonal crosses a number, then the left cell take value 1 and the +number is prime. The parallel version of this algorithm works in real time n. This C -sequential version is slower as it works in O(n*log n). But you have some +sequential version is slower as it works in `O(n*log n)`. But you have some nice picture instead... the cost is a constant number of operation for each character printed on the screen. -### Why do you wrote it? +### Why did I write this ? -Let's just quote the FAQ : +Let's just quote the [FAQ](/faq.md): Q: Are there types of entries that are submitted so frequently that the judges get tired of them? @@ -95,12 +95,13 @@ some complex state machine/table to generate small primes and print them. ### The way it works This program simply prints the space-time diagram of some particular -cellular automaton. The automaton is a 9-state automaton by Korec in 1998. +cellular automaton. The automaton is a 9-state automaton by [Ivan +Korec](https://sk-m-wikipedia-org.translate.goog/wiki/Ivan_Korec?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=en-US&_x_tr_pto=wapp) in 1998. It is an optimization of an old automaton for recognizing primes designed -by Fischer in 1965. +by [Fischer](http://richardallenfischer.com) in 1965. -The table of the automaton is encoded into the string e and consists of -345 transitions of the kind f(left,middle,right). This encoding into e +The table of the automaton is encoded into the string `e` and consists of +345 transitions of the kind ff(left,middle,right)`. This encoding into `e` is obfuscated to reduce its size, restrict it to characters 32 to 127 and guarantee a constant time. diff --git a/2001/rosten/README.md b/2001/rosten/README.md index dc74ddcf3..e6ef5adb9 100644 --- a/2001/rosten/README.md +++ b/2001/rosten/README.md @@ -1,14 +1,8 @@ # Best abuse of the user - Edward Rosten - Oxford University - 34 The Chilterns - Gloucester Green - Oxford - OX1 2DF - United Kingdom - - http://users.ox.ac.uk/~scat1148 +Edward Rosten +UK + ## To build: @@ -19,9 +13,14 @@ make ## To run: ```sh -./rosten number +./rosten [number] ``` +WARNING: this will mess with your mouse and can make it hard to quit the +program. Use at your own risk. + +NOTE: number is floating point. + ## Try: ```sh @@ -42,115 +41,120 @@ cursor) in the wrong way. :-) ## Author's remarks: -NAME +### NAME - rosten - make the mouse act as if it has been greased +`rosten` - make the mouse act as if it has been greased -SYNOPSIS +### SYNOPSIS - rosten [greasiness] +```sh +./rosten [greasiness] +``` -DESCRIPTION +### DESCRIPTION - This program is designed primarily to make your X windows interface more - obfuscated. Try doing something mouse driven (such as using a mouse - driven editor on this program) whilst it is running. If you're not sure - what it does, looking at the code should give a fair idea. +This program is designed primarily to make your X windows interface more +obfuscated. Try doing something mouse driven (such as using a mouse +driven editor on this program) whilst it is running. If you're not sure +what it does, looking at the code should give a fair idea. - It also has a [cat] man page if you want to install it as a `utility'. +It also has a [cat] man page if you want to install it as a 'utility'. -OPTIONS +### OPTIONS - It only takes one optional option: the greasiness factor. This is the - number that the speed is divided by on each iteration. The default is - 1.03. A setting of 1 (no friction is fun), as is 0.99. +It only takes one optional option: the greasiness factor. This is the +number that the speed is divided by on each iteration. The default is +1.03. A setting of 1 - no friction - is fun as is 0.99. - Being an X program, it recognised the DISPLAY variable. +Being an X program, it recognised the `DISPLAY` variable. -PORTABILITY +### PORTABILITY - The program is very portable, even to non X architectures. All that is - required is a large desk and some good grease. +The program is very portable, even to non X architectures. All that is +required is a large desk and some good grease. -COMMENTS +### COMMENTS - It is really rather surprising that code like this should not only be - portable, but compile with almost no warnings on most of the compilers - tested. It's a kind of shame that none of the compilers do anything - like this: +It is really rather surprising that code like this should not only be +portable, but compile with almost no warnings on most of the compilers +tested. It's a kind of shame that none of the compilers do anything +like this: - $make greasymouse - cc greasymouse.c -o greasymouse -lX11 - greasymouse.c:30: This macro should have more text and spaces in it - greasymouse.c:32: This is a really stupid way to perform this operation - greasymouse.c:42: This program would look better with a newline here - greasymouse.c:48: That's a really silly thing to do - greasymouse.c:55: So is that - ... - greasymouse.c:58: This program is rubbish. I'm not going to link it. +```sh +$ make greasymouse +cc greasymouse.c -o greasymouse -lX11 +greasymouse.c:30: This macro should have more text and spaces in it +greasymouse.c:32: This is a really stupid way to perform this operation +greasymouse.c:42: This program would look better with a newline here +greasymouse.c:48: That's a really silly thing to do +greasymouse.c:55: So is that +... +greasymouse.c:58: This program is rubbish. I'm not going to link it. +``` - The code is best viewed with tabstops every 8 spaces. +The code is best viewed with [tab stops](https://en.wikipedia.org/wiki/Tab_stop) every 8 spaces. -BUGS +### BUGS - The mouse gets stuck completely if you give it an option of less - than 1 and leave it for too long. This is quite annoying if it - didn't leave the terminal if was run from in focus. +The mouse gets stuck completely if you give it an option of less +than 1 and leave it for too long. This is quite annoying if it +didn't leave the terminal it was run from in focus. - It gets very jerky if the processor is being used. There are - better time functions than clock() but I haven't used them. +It gets very jerky if the processor is being used. There are +better time functions than `clock()` but I haven't used them. - It deflects slightly when it gets very slow. +It deflects slightly when it gets very slow. - It annoys other people if you run it on their display too - often. Maybe I should make future versions print funny jokes to - keep the humor fresh. +It annoys other people if you run it on their display too +often. Maybe I should make future versions print funny jokes to +keep the humor fresh. - It's pretty ropey over a 56K modem. +It's pretty ropey over a 56K modem. - It's even ropier over a 56K modem and tunneled through 3 ssh links. +It's even ropier over a 56K modem and tunneled through 3 ssh links. -WARNINGS +### WARNINGS - Pages and pages and pages of things, with GCC at any rate. +Pages and pages and pages of things, with GCC at any rate. - It suggests loads of ()'s where they're not needed. +It suggests loads of `()`s where they're not needed. - It reckons I have not used some of the values I have computed. I - would never do a thing like that: I just haven't used them in - the way it's used to. +It reckons I have not used some of the values I have computed. I +would never do a thing like that: I just haven't used them in +the way it's used to. - The MIPS compiler suggests an == instead of an = in expressions - such as: +The MIPS compiler suggests an `==` instead of an `=` in expressions +such as: - &&(a=b) +```c +&&(a=b) +``` - but I its suggestions would break my program. It also reckons - that r() has no prototype. +but its suggestions would break my program. It also reckons +that `r()` has no prototype. - Giving the -pedantic option to the MIPS compiler causes it to generate - warnings about its own header files, but not any extra ones with this - program. +Giving the `-pedantic` option to the MIPS compiler causes it to generate +warnings about its own header files, but not any extra ones with this +program. - With all warnings enabled, the DEC compiler, oddly enough finds some - problems with its own include files, but none with my program. +With all warnings enabled, the DEC compiler, oddly enough finds some +problems with its own include files, but none with my program. -ERRORS +### ERRORS - The DEC compiler of this version: +The DEC compiler of this version: `DEC C V5.6-079 on Digital UNIX V4.0 (Rev. +878)` - DEC C V5.6-079 on Digital UNIX V4.0 (Rev. 878) - - can't compile the code. It thinks that preprocessor lines can not have - whitespace preceding the #. Moving the preprocessor directives to the - beginning of the line wrecks the layout but makes it compile. +can't compile the code. It thinks that preprocessor lines can not have +whitespace preceding the `#`. Moving the preprocessor directives to the +beginning of the line wrecks the layout but makes it compile. ## Copyright and CC BY-SA 4.0 License: diff --git a/2001/schweikh/README.md b/2001/schweikh/README.md index ed6e615e1..8be091c6a 100644 --- a/2001/schweikh/README.md +++ b/2001/schweikh/README.md @@ -1,12 +1,8 @@ # Best one-liner - Jens Schweikhardt - Marconi Communications - Schlartaeckerweg 3 - D-71384 Weinstadt - Germany - - http://www.schweikhardt.net/ +Jens Schweikhardt +Germany + ## To build: @@ -20,6 +16,16 @@ make ./schweikh string string2 ``` +### INABIAF - it's not a bug it's a feature! :-) + +This program will very likely crash or do something else if you do not give it +two args. + +Note also that the glob pattern must match the whole string. See the author's +comments for details and a workaround. + +There's also no way to escape meta characters. + ## Try: ```sh @@ -35,17 +41,16 @@ Do you get the pattern here? ## Author's remarks: This one-liner program is a glob pattern matcher. It understands -the glob characters `*' meaning `zero or more characters' and -`?' meaning exactly one character, just like your unix shell. +the glob characters `*` meaning 'zero or more characters' and +`?` meaning exactly one character, just like your unix shell. -Run it with two args, the string and the glob pattern. The exit -status is 0 (shell true) when the pattern matches, 1 otherwise. -The glob pattern must match the whole string, so you may want to -use * at the beginning and end of the pattern if you are looking -for something in the middle. +Run it with two args, the string and the glob pattern. The exit status is 0 +(shell true) when the pattern matches, 1 otherwise. The glob pattern must match +the whole string, so you may want to use `*` at the beginning and end of the +pattern if you are looking for something in the middle. You can use it for your shell scripting needs similar to a silent grep -(and without stdout redirected to /dev/null): +(and without stdout redirected to `/dev/null`): ```sh if prog "${VARIABLE}" ''; then @@ -55,32 +60,35 @@ else fi ``` -Bugs: there is no way to escape the meta characters. Dammit Jim, I'm a +### Bugs + +There is no way to escape the meta characters. Dammit Jim, I'm a one-liner, not a regexp lib. -All obfuscation is obviously in the recursive m() function, an 86 +All obfuscation is obviously in the recursive `m()` function, an 86 character glob pattern evaluator, returning nonzero for a match: -* just a single complex return expression. -* nested ternary operator ?: to save on if/else verbosity. -* short circuiting && and || to save even more on if/else verbosity. -* Subtraction instead of an equality operator in "*t - 42". -* ASCII codes for '*' and '?'. -* careful use of blanks even though this year's rules have extended + +* Just a single complex return expression. +* Nested ternary operator `?:` to save on if/else verbosity. +* Short circuiting `&&` and `||` to save even more on if/else verbosity. +* Subtraction instead of an equality operator in `*t - 42`. +* ASCII codes for `*` and `?`. +* Careful use of blanks even though this year's rules have extended that resource limit. -* the source is a complete preprocessed C program. Because it communicates +* The source is a complete preprocessed C program. Because it communicates with the world out there by means of argv and the exit status, there is no need for stdio bloat. An asm guru could surely squeeze this program in less than a screenful. -* indent(1) is probably not too helpful. +* `indent(1)` is probably not too helpful. The recursion wonderfully and magically takes care of iteration and backtracking. I could tell you how it works but then I would have to -kill^Wrequest an NDA from you :-) Run it under a debugger with several -inputs, it will be quite helpful and instructive. Handling of '?' is -straightforward; for '*' start out with '*foo' and 'foo*' against 'foo'. -How does it deal with sequences of adjacent `*'? How could this be -improved? If all else fails, recode the ?: operators with if/else and -try again. For extra credit implement character classes like [a-z]. +kill request a NDA from you :-) Run it under a debugger with several +inputs, it will be quite helpful and instructive. Handling of `?` is +straightforward; for `*` start out with `*foo` and `foo*` against `foo`. +How does it deal with sequences of adjacent `*`? How could this be +improved? If all else fails, recode the `?:` operators with if/else and +try again. For extra credit implement character classes like `[a-z]`. ## Copyright and CC BY-SA 4.0 License: diff --git a/2001/westley/.gitignore b/2001/westley/.gitignore index 50cb97837..41c62376a 100644 --- a/2001/westley/.gitignore +++ b/2001/westley/.gitignore @@ -2,5 +2,5 @@ westley westley.alt westley2 westley2.c -westley3 -westley3.c +westley.punch +westley.sort diff --git a/2001/westley/Makefile b/2001/westley/Makefile index 04e7662ee..05a426a77 100644 --- a/2001/westley/Makefile +++ b/2001/westley/Makefile @@ -63,7 +63,7 @@ CDEFINE= # Include files that are needed to compile # -CINCLUDE= +CINCLUDE= -include stdio.h # Optimization # @@ -113,7 +113,7 @@ PROG= ${ENTRY} # OBJ= ${PROG}.o DATA= -TARGET= ${PROG} +TARGET= ${PROG} ${PROG}.sort ${PROG}.punch # ALT_OBJ= ${PROG}.alt.o ALT_TARGET= ${PROG}.alt @@ -143,6 +143,10 @@ westley2: westley2.c westley3: westley3.c ${CC} ${CFLAGS} $< -o $@ ${LIBS} +${PROG}.sort: ${PROG}.sort.c + ${CC} ${CFLAGS} $< -o $@ ${LIBS} + + # alternative executable # alt: data ${ALT_TARGET} diff --git a/2001/westley/README.md b/2001/westley/README.md index 12217d6fa..140a5a51b 100644 --- a/2001/westley/README.md +++ b/2001/westley/README.md @@ -1,12 +1,8 @@ # Best position-independent code - Brian Westley - Firesign Theatre webmaster - 1906 James Ave - St. Paul, MN 55105 - USA - - http://www.westley.org +Brian Westley +US + ## To build: @@ -22,20 +18,20 @@ make ## Try: +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) added the script +[westley.sh](westley.sh) to automate a heap of commands that we, the IOCCC +judges, suggested, as well as some additional ones that he thought would be fun. +These include the below sort and punch card versions that he added, described +below, based on the author's remarks. Thank you Cody! + ```sh -./westley < westley.c > westley2.c -make westley2 -echo 'Bozos, please deflate shoes before entering the bus!'| ./westley2 -sort -b < westley2.c > westley3.c -make westley3 -./westley3 < westley.c | diff - westley.c -./westley3 < westley.c | diff - westley2.c -./westley3 < westley.c | diff - westley3.c +./westley.sh ``` -### Alternate code +### Alternate code: -An alternate version of this entry, `westley.alt.c`, is provided. This alternate code may be less portable. +An alternate version of this entry, [westley.alt.c](westley.alt.c), is provided. +This alternate code might be less portable. To compile this alternate version: @@ -45,7 +41,27 @@ make alt Use `westley.alt` as you would `westley` above. -## Judges' remarks +### Sorted code: + +The author stated that one can sort (with ignoring leading blanks i.e. `sort +-b`) the code by line and it will always sort the order of the input. + +Use `westley.sort` as you would `westley` above. + +### Punch card code: + +The author also stated that if you just sort the code you'll get the with +`sort`) version that just prints out the punch card. Cody put this in +[westley.punch.c](westley.punch.c) specifically so that Westley can punch +everyone in the face! :-) This is also compiled by default. + +To use, try: + +```sh +echo 'Brian Westley does it again!' | ./westley.punch 2>/dev/null +``` + +## Judges' remarks: Try copying the source to a new file and changing around the order of the lines. Does it produce the exact same output? @@ -53,16 +69,19 @@ order of the lines. Does it produce the exact same output? By changing the order of the source, figure out in how many different ways this program can transform input to output. -This assortment obfuscated lines takes position-independant code +This assortment obfuscated lines takes position-independent code to a new level! :-) -## Author's remarks +We find it amazing that with just 28 lines of code (not counting comments and +blank lines) there are `28!` or ``304,888,344,611,713,860,501,504,000,000`` +versions of the program, all valid C! -Punch cards, or Hollerith cards, were becoming obsolete just -as C was becoming more popular*; this is rather unfortunate, -because C has an advantage over many other languages when it -comes to punch cards - C programs can be written to be "drop -proof". +## Author's remarks: + +[Punch cards](https://en.wikipedia.org/wiki/Punched_card), or Hollerith cards, +were becoming obsolete just as C was becoming more popular\*; this is rather +unfortunate, because C has an advantage over many other languages when it comes +to punch cards - C programs can be written to be "drop proof". Consider the following C program: @@ -76,7 +95,7 @@ c(){printf("C");} This program will compile and run no matter what order the lines are in. If you punch it on cards (one line of code per card, naturally) and drop them, you don't need to put them in -any particular order**; it will always produce "ABC" as output. +any particular order\*\*; it will always produce `ABC` as output. You can also use global variables: @@ -96,9 +115,9 @@ test(a,b){return a;} main(){if (test(0,1)) printf("T"); else printf("F");} ``` -This program will print out "T" if the #define statement -falls between the declaration of test() and its use in -main(), otherwise it will print out "F". Furthermore, +This program will print out `T` if the `#define` statement +falls between the declaration of `test()` and its use in +`main()`, otherwise it will print out `F`. Furthermore, you can use the same call to test() repeatedly in different lines to return different values: @@ -120,16 +139,20 @@ number generator... Of course, there are drawbacks to C programming on punch cards; an 80-character line limit can be restricting, and (to be maximally portable) you need to use trigraphs for -the characters "^[]{}\" (these aren't found on every +the characters `^[]{}\` (these aren't found on every keypunch, and have various encodings). My C program entry does the following: -1) reads in lines -2) rearranges the lines, or not -2a) if it rearranges the lines, they are sorted or scrambled -3) reverses the order of the lines, or not -4) prints out the lines as either text or EBCDIC punch cards. +1. Reads in lines. + +2. Rearranges the lines, or not. + - if it rearranges the lines, they are sorted or scrambled. + +3. Reverses the order of the lines, or not. + +4. Prints out the lines as either text or +[EBCDIC](https://en.wikipedia.org/wiki/EBCDIC) punch cards. The code, as written, scrambles the input and prints it out as normal text, so you can simulate 'dropping' the cards. @@ -137,19 +160,19 @@ You can repeatedly scramble the code to get all 12 variants (but the scrambling isn't very random; it's just a bubble sort with a random number, so some variants are more common than others). You can also just swap the arguments in the -calls to t() in all combinations to get all the variations. +calls to `t()` in all combinations to get all the variations. If you sort the lines, you will get the version that just prints out the input as punch cards (you will need to display at least 82 columns of text, or clip the last few chars by -piping it through "sed s/...$//"). If you use this on the -original code, you will see that it spells out "HOLLERITH" +piping it through `sed s/...$//`). If you use this on the +original code, you will see that it spells out `HOLLERITH` when punched on cards (you can see the tall, thin letters -spelling out "HOLLERITH" if you turn the C code sideways). -You will also see why "/KC 0000 K" is a "Hollerith emoticon". +spelling out `HOLLERITH` if you turn the C code sideways). +You will also see why `/KC 0000 K` is a `Hollerith emoticon`. Unrecognized characters are punched as a lace column. (You can see an ASCII simulation of the code as punch cards -by looking at card.gif) +by looking at `card.gif`.) For a nice test pattern, try @@ -158,29 +181,30 @@ For a nice test pattern, try ``` If you want to analyze the program, sorting the lines while -ignoring leading blanks works best (sort -b). This will +ignoring leading blanks works best (`sort -b`). This will produce the version that just reverses the line order, and the routines in the code are in a sensible order. This program should work on EBCDIC computers. It assumes -that the time_t ptr param to time() will work with an int -ptr, and that "passing through" a char[][] array as a simple -char* is ok. Your compiler MUST understand trigraphs, or it +that the `time_t` ptr param to `time()` will work with an `int` +ptr, and that "passing through" a `char[][]` array as a simple +`char *` is OK. Your compiler MUST understand trigraphs, or it will miss the trigraph backslash before the double quote in -the K string and complain about a malformed string; for GNU -C, use -ansi or -trigraphs. Entering a line of more than 80 +the `K` string and complain about a malformed string; for GNU +C, use `-ansi` or `-trigraphs`. Entering a line of more than 80 characters, or more than 81 lines, will jam the card reader. -I've used the a[b] ==> *(a+b) trick, because this is -actually shorter than the trigraph version of a??(b??). +I've used the `a[b]` ==> `*(a+b)` trick, because this is +actually shorter than the trigraph version of `a??(b??)`. With 28 lines of code (not counting the blank lines or the -comment), there are technically 28! different programs, or -304,888,344,611,713,860,501,504,000,000 different versions, +comment), there are technically `28!` different programs, or +`304,888,344,611,713,860,501,504,000,000` different versions, all legal C. -*except in Florida voting machines -**all cards must be face down, nine-edge first, of course. +\* except in Florida voting machines + +\*\* all cards must be face down, nine-edge first, of course. ## Copyright and CC BY-SA 4.0 License: diff --git a/2001/westley/westley.punch.c b/2001/westley/westley.punch.c new file mode 100644 index 000000000..41738daa3 --- /dev/null +++ b/2001/westley/westley.punch.c @@ -0,0 +1,37 @@ + + + + + + + + + T(c,r) ??< return Y(c, r)?'??(' :' '; ??> + W(r,a,b,c)?? + /* { /KC 0000 K } */ + char*B=" yz0123456789"; + U(c,i)char*c; ?? + char* B,*r; X(c,k)?? + L(c,i,j)char c??(81??)??(81??);?? + char*r= "008y8yy8yyyyz8z8z88888z0yyz888 8888 88y00zz00z0088"; + E(r,s)char*r,*s; ??< if(t( 0,1)&& F(r,s)<0)G(r,s); ??> + char*d= "yyzzyzz zz z0y000 zz 00yzz00y00yzz Brian Westley zyy00yy0yy 0" ; ; ; + t(a,b)?? +#define t(a,b) t(b,a) +A(i ,c,j ,k) char *c; ??< for(j= -1; ++j +D(c,i,j) char c??(81??)??(81??);?? +F(r,s)char*r,*s; ?? +G(r,s)char*r,*s; ?? +H()?? return rand()-rand(); ??> +J(i,c,j)char*c; ?? +M(i,c)char c??(81??)??(81??);?? +P(c)char*c; ?? +Q(t,i)??< printf(t?" ":"|"); for(; i<80; i++) printf("_"); puts(t?"_":"|"); ??> +R(c,r) char *c; ??< printf( "/%-80s|??/n" ,c); for (; r< 13; r++)S (c,r,0); ??> +S(c,r,i)char*c; ?? +V(c,k,i) char*k; ?? +char* K;Y (c ,r) ??< int i=V ( tolower (c) ,K); return(i <0)?1 :Z(c ,r, i); ??> +char* d,*m,*B; Z(c,i,k)?? +char*K= "gh$j|lm'pq&rvz#);@_winky,.%/+*!=3-284106579 (:obfuscated??/?" ; ; +char*m= "7831734578 9547693564569528334164263z284106579 52626423135477"; ; ; ; +main(i)?? diff --git a/2001/westley/westley.sh b/2001/westley/westley.sh new file mode 100755 index 000000000..2e92accca --- /dev/null +++ b/2001/westley/westley.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +echo "./westley < westley.c 2>/dev/null > westley2.c" +./westley < westley.c 2>/dev/null > westley2.c +make westley2 2>/dev/null 1>&2 +echo +echo "echo 'Bozos, please deflate shoes before entering the bus!'| ./westley2 2>/dev/null" +echo 'Bozos, please deflate shoes before entering the bus!'| ./westley2 2>/dev/null +echo + +make westley.sort 2>/dev/null 1>&2 +echo +echo "./westley.sort < westley.c 2>/dev/null | diff - westley.c" +# SC2094 (info): Make sure not to read and write the same file in the same pipeline. +# shellcheck disable=SC2094 +./westley.sort < westley.c 2>/dev/null | diff - westley.c +echo "./westley.sort < westley.c 2>/dev/null | diff - westley2.c" +./westley.sort < westley.c 2>/dev/null | diff - westley2.c +echo "./westley.sort < westley.c 2>/dev/null | diff - westley.sorted.c" +./westley.sort < westley.c 2>/dev/null | diff - westley.sorted.c +echo "./westley.sort < westley.c 2>/dev/null | diff - westley.punch.c" +./westley.sort < westley.c 2>/dev/null | diff - westley.punch.c + +echo +# SC2028 (info): echo may not expand escape sequences. Use printf. +# shellcheck disable=SC2028 +echo "printf \"1\n\4\n5\" | ./westley 2>/dev/null" +printf "1\n4\n5" | ./westley 2>/dev/null + +echo +# SC2028 (info): echo may not expand escape sequences. Use printf. +# shellcheck disable=SC2028 +echo "printf \"1\n\4\n5\" | ./westley 2>/dev/null" +printf "1\n4\n5" | ./westley 2>/dev/null + +echo +echo "echo 'Hello, world!' | ./westley.punch 2>/dev/null" +echo 'Hello, world!' | ./westley.punch 2>/dev/null diff --git a/2001/westley/westley.sort.c b/2001/westley/westley.sort.c new file mode 100644 index 000000000..99591b5bb --- /dev/null +++ b/2001/westley/westley.sort.c @@ -0,0 +1,37 @@ + + + + + + + + +#define t(a,b) t(b,a) + /* { /KC 0000 K } */ +A(i ,c,j ,k) char *c; ??< for(j= -1; ++j +D(c,i,j) char c??(81??)??(81??);?? + E(r,s)char*r,*s; ??< if(t( 0,1)&& F(r,s)<0)G(r,s); ??> +F(r,s)char*r,*s; ?? +G(r,s)char*r,*s; ?? +H()?? return rand()-rand(); ??> +J(i,c,j)char*c; ?? + L(c,i,j)char c??(81??)??(81??);?? +M(i,c)char c??(81??)??(81??);?? +P(c)char*c; ?? +Q(t,i)??< printf(t?" ":"|"); for(; i<80; i++) printf("_"); puts(t?"_":"|"); ??> +R(c,r) char *c; ??< printf( "/%-80s|??/n" ,c); for (; r< 13; r++)S (c,r,0); ??> +S(c,r,i)char*c; ?? + T(c,r) ??< return Y(c, r)?'??(' :' '; ??> + U(c,i)char*c; ?? +V(c,k,i) char*k; ?? + W(r,a,b,c)?? + char* B,*r; X(c,k)?? +char* K;Y (c ,r) ??< int i=V ( tolower (c) ,K); return(i <0)?1 :Z(c ,r, i); ??> +char* d,*m,*B; Z(c,i,k)?? + char*B=" yz0123456789"; +char*K= "gh$j|lm'pq&rvz#);@_winky,.%/+*!=3-284106579 (:obfuscated??/?" ; ; + char*d= "yyzzyzz zz z0y000 zz 00yzz00y00yzz Brian Westley zyy00yy0yy 0" ; ; ; +char*m= "7831734578 9547693564569528334164263z284106579 52626423135477"; ; ; ; + char*r= "008y8yy8yyyyz8z8z88888z0yyz888 8888 88y00zz00z0088"; +main(i)?? + t(a,b)?? diff --git a/2001/williams/README.md b/2001/williams/README.md index fa5491ba1..810fbd260 100644 --- a/2001/williams/README.md +++ b/2001/williams/README.md @@ -1,9 +1,7 @@ # Best Graphic Game - John Williams - 941 E 25 S - Lindon UT 84042 - USA +John Williams +US ## To build: @@ -25,11 +23,12 @@ echo "Do or do not. There is no try." ## Judges' remarks: -A strange game. The only winning move is not to play. No, really; you can't -actually win. :) +[A strange game. The only winning move is not to +play](https://en.wikipedia.org/wiki/WarGames). No, really; you can't +actually win. :) -The formatting really wants a wide screen; if you can't read it that way, -it's the standard "three triangles around a circular" logo for nukes. +The formatting really wants a wide screen; if you can't read it that way, it's +the standard "three triangles around a circular" logo for nukes. This is a pretty straightforward game. @@ -37,8 +36,8 @@ This is a pretty straightforward game. What this program does: -It plays Missile Command, complete with MIRVs, smart bombs, -extra cities, and scoring. +It plays [Missile Command](https://en.wikipedia.org/wiki/Missile_Command), +complete with MIRVs, smart bombs, extra cities, and scoring. Command line arguments and input files are ignored. @@ -51,18 +50,18 @@ points for each city left at the end of a level. The game ends when you lose all your cities, although you will have to wait until the level finishes raining down to see your final score. - +### Obfuscation The main obfuscation technique is the need to compress the code to fit all the functionality within the size limits. I could not have included -smart bombs without the rule excluding { } ; characters in the counts. -All of the #defines are there to reduce code size. +smart bombs without the rule excluding `{};` characters in the counts. +All of the `#define`s are there to reduce code size. On the other hand, I did waste a few characters in order to include some rather obfuscated math in the program. It uses fixed-point arithmetic, resulting in the overuse of bitwise shift operators. -Another example is (x|1), which is used in a couple different ways. -The purpose of A/(x|1) is probably obvious, but what does (x|1)%2 do? +Another example is `(x|1)`, which is used in a couple different ways. +The purpose of `A/(x|1)` is probably obvious, but what does `(x|1)%2` do? ## Copyright and CC BY-SA 4.0 License: diff --git a/2004/README.md b/2004/README.md index 5b8099fde..c1005b267 100644 --- a/2004/README.md +++ b/2004/README.md @@ -1,83 +1,82 @@ -2004 marked the "The Seventeenth International Obfuscated C Code Contest" +# [2004](/years.html#2004) marked the "The Seventeenth International Obfuscated C Code Contest" -Standard IOCCC stuff --------------------- +## Standard IOCCC stuff -Look at the README.md file for the given winner for information -on how to compile the winner and how to run the winning program. +Look at the `README.md` file for the given winner for information +on how to compile the entry and how to run the winning program. Look at the winning source and try to figure how it does what it does! You may then wish to look at the Author's remarks for even more details. The IOCCC has a web site and now has a number of international mirrors. -The primary site can be found at, +The primary site can be found at . - http://www.ioccc.org/ +Use `make(1)` to compile entries. It is possible that on non-Unix / non-Linux +systems the `Makefile` needs to be changed. See the `Makefile` for details. -Use make to compile entries. It is possible that on non-Un\*x / non-Linux -systems the makefile needs to be changed. See the Makefile for details. - -Read over the makefile for compile/build issues. Your system may +Read over the `Makefile` for compile/build issues. Your system may require certain changes (add or remove a library, add or remove a -#define). +`#define`). Some ANSI C compilers are not quite as good as they should be. If -yours is lacking, you may need to compile using gcc instead of your +yours is lacking, you may need to compile using `gcc` instead of your local compiler. -Remarks on some of the entries ------------------------------- +## Remarks on some of the entries + +We believe you will be impressed with this year's winners. The [Best of +Show](gavin/gavin.c) is a fine example of obfuscation. But don't ignore the +other winners! There are games, utilities, programs that output images and a +one-liner that is incredibly compact for what it can do. + +The [Best Abuse of the Guidelines](hibachi/hibachi.c) is technically allowed by +the rules. This year we allowed it due to the functionality of the program. +This entry is one of the easiest to read! Don't assume you can win using +similar techniques next time ... :-) + +This year a [single person](/winners.html#Daniel_Vik) won two awards! We also +had repeat winners with their 6th, 4th and 2nd winning entries this year! +(Please note that judging is done completely anonymously. Be warned that we may +disqualify entries that reveal the identity of the submitter.) + +### Remarks on some losing entries There were some outstanding entries that did not win. Unfortunately some very good entries lost because they: - + depended too much on non-portable side effects in expressions; - + depended too much on a particular byte order; - + required the use of a special script, data file or pseudo-machine - language that was not supplied with the entry. +* depended too much on non-portable side effects in expressions; and/or +* depended too much on a particular byte order; and/or +* required the use of a special script, data file or pseudo-machine + language that was not supplied with the entry. We hope the authors of some of those entries will fix and re-submit them for the next IOCCC. -We believe you will be impressed with this year's winners. The Best -of Show is a fine example of obfuscation. But don't ignore the other -winners! There are games, utilities, programs that output images and -a one-liner that is incredibly compact for what it can do. - -The Best Abuse of the Guidelines is technically allowed by the rules. -This year we allowed it due to the functionality of the program. This -entry is one of the easiest to read! Don't assume you can win using -similar techniques next time ... :-) - -This year a single person won two awards! We also had repeat winners -with their 6th, 4th and 2nd winning entries this year! (Please note that -judging is done completely anonymously. Be warned that we may disqualify -entries that reveal the identity of the submitter). - - -Final Comments --------------- +## Final Comments Please feel free to send us comments and suggestions about the -competition, this README or anything else that you would like to see in -future contests. +competition, this [README.md](README.md) or anything else that you would like to +see in future contests. If you use, distribute or publish these entries in some way, please drop us a line. We enjoy seeing who, where and how the contest is used. If you have problems with any of the entries, AND YOU HAVE A FIX, please -send us the fix (patch file or the entire changed file). +send us the fix please submit your fixes fix as a [GitHub pull +request](https://github.com/ioccc-src/temp-test-ioccc/pulls). -For the latest information on how to contact the IOCCC Judges please visit +We will be happy to credit those who submit successful [GitHub pull +requests](https://github.com/ioccc-src/temp-test-ioccc/pulls) in the entry's +`README.md`. + +For the latest information on how to contact the [IOCCC +Judges](https://www.ioccc.org/judges.html) please visit +. http://www.ioccc.org/contact.html -Watch: - - http://www.ioccc.org/ - -for news of the next contest. +For news of the next contest watch . =-= diff --git a/2004/anonymous/README.md b/2004/anonymous/README.md index 907a4c558..b9d4ae0c2 100644 --- a/2004/anonymous/README.md +++ b/2004/anonymous/README.md @@ -1,9 +1,8 @@ # Best use of "Precious" Lines - The author wishes to remain anonymous - Singapore - - http://bicoherent.topcities.com/ +The author wishes to remain anonymous +Singapore + ## To build: @@ -26,53 +25,68 @@ make ## Judges' remarks: -Then view the output using your favourite "pgm" viewer. If you -don't have a "pgm" viewer then we suggest the "netpbm" toolkit -(http://netpbm.sourceforge.net/) to convert the image to a -graphics format that you can view - most graphical Web browsers -can display PNG or JPEG images. +Then view the output using your favourite +[pgm](https://en.wikipedia.org/wiki/Netpbm#PGM_example) viewer. If you don't +have a `pgm` viewer then we suggest the [netpbm +toolkit](https://netpbm.sourceforge.net) to convert the image to a graphics +format that you can view. Most graphical web browsers can display PNG or JPEG +images. -BTW: if you haven't read The Lord of the Rings what are you waiting for? :-) You'll -find out the source of the text above though you'll see that there are some -circumflexes missing! That's okay though due to I/O of the entry and in earlier -drafts sometimes the û with an umlaut had a H added to it. The real text is: +p.s. Frodo lives! + +### An important aside :-) + +BTW: if you haven't read [The Lord of the +Rings](https://en.wikipedia.org/wiki/The_Lord_of_the_Rings) what are you waiting for? :-) +You'll find out the source of the text above though you'll see that there are +some circumflexes missing! That's okay though due to I/O of the entry and in +earlier drafts sometimes the û with an umlaut had no umlaut but H after the `u` +it. The real text is: > Ash nazg durbatulûk, ash nazg gimbatul, ash nazg thrakatulûk, agh > burzum-ishi krimpatul. -which when translated from Black Speech means: +which when translated from [Black +Speech](https://www.glyphweb.com/arda/b/blackspeech.html) means: -> One Ring to rule them all, One Ring to find them, -> One Ring to bring them all and in the darkness bind them. +> [One Ring](https://www.glyphweb.com/arda/o/onering.html) to rule them all, [One +Ring](https://www.glyphweb.com/arda/o/onering.html) to find them, +> [One Ring](https://www.glyphweb.com/arda/o/onering.html) to bring them all and in the darkness bind them. -p.s. Frodo lives! - ## Author's remarks: This program takes a single command line argument, transcribes the argument text into Tolkien's Elvish letters, and writes the -transcription to standard output as a portable graymap (PGM) file. +transcription to standard output as a [portable +graymap](https://en.wikipedia.org/wiki/Netpbm#PGM_example) (PGM) file. -The specific transcription mode is the Black Speech Tengwar mode, as -used in the inscription on the One Ring. The program handles the +The specific transcription mode is the [Black +Speech](https://www.glyphweb.com/arda/b/blackspeech.html) ([Tengwar +mode](https://www.glyphweb.com/arda/t/tengwar.html)), as +used in the inscription on the [One +Ring](https://www.glyphweb.com/arda/o/onering.html). The program handles the following digraphs: -- "gh", "sh", "th": the corresponding tengwar are output for these - specific sounds -- "mh" denotes the full tengwa for [m]; "m" by itself means a - horizontal bar above the next letter -- "rh" denotes the [r\] tengwa -- "uh" denotes the tehta for long vowel [u:] -- "zh" selects the up-reaching tengwa for [z], while "z" selects the - down-reaching one +- `gh`, `sh`, `th`: the corresponding +[tengwar](https://www.glyphweb.com/arda/t/tengwar.html) are output for these +specific sounds. +- `mh` denotes the full [tengwa](https://www.glyphweb.com/arda/t/tengwar.html) +for `[m]`; `m` by itself means a horizontal bar above the next letter. +- `rh` denotes the `[r]` [tengwa](https://www.glyphweb.com/arda/t/tengwar.html). +- `uh` denotes the [tehta](https://www.glyphweb.com/arda/t/tehtar.php) for long +vowel `[u:]`. +- `zh` selects the up-reaching +[tengwa](https://www.glyphweb.com/arda/t/tengwar.html) for `[z]`, while `z` +selects the down-reaching one. Punctuation marks other than commas and periods are ignored, as are whitespace characters. In addition, the argument text must be entirely in lower case. -The following command thus writes a rendering of the Ring inscription to -the file out.pgm: +The following command thus writes a rendering of the [Ring +inscription](https://www.glyphweb.com/arda/r/ringinscription.html) to +the file `anonymous.pgm`: ```sh ./anonymous "ash nazg durhbatuluhk, ash nazg gimbatul, \ @@ -84,9 +98,11 @@ constraints, the program uses rather inefficient algorithms, so it may waste a lot of time and space even when rendering moderately long strings. -The code contains a vector font which was derived by toying with Harri -Pera:la:'s Tengwar Cursive font. Currently, only the glyphs used in the -Ring inscription are included in the font. +The code contains a vector font which was derived by toying with [Harri +Perälä](https://alboin.fi)'s [Tengwar Cursive +font](https://alboin.fi/tengwar.htm). Currently, only the glyphs used in the +[Ring inscription](https://www.glyphweb.com/arda/r/ringinscription.html) are +included in the font. ## Copyright and CC BY-SA 4.0 License: diff --git a/2004/arachnid/README.md b/2004/arachnid/README.md index 031078215..29412b7bf 100644 --- a/2004/arachnid/README.md +++ b/2004/arachnid/README.md @@ -1,12 +1,8 @@ # Best use of Vision - Nick Johnson - 25 Harvey Tce - Richmond - Christchurch - New Zealand - - http://www.notdot.net/ +Nick Johnson +New Zealand + ## To build: @@ -32,41 +28,42 @@ and then try: ./arachnid arachnid.c ``` -## Judges' remarks +## Judges' remarks: The fun part comes when you realize that the maze scrolls. The overall visual effect is quite pleasing (at least on some displays), and, well, it's a lot of fun. Navigation is through the use of the "wasd" inverted-T formation on -Qwerty keyboards. Rogue players, vi users, and Dvorak typists are +QWERTY keyboards. Rogue players, vi users, and Dvorak typists are invited to get lost! -## Author's remarks +## Author's remarks: This program accepts ASCII formatted mazes as input, and renders -them onscreen for the user to explore, complete with Line Of Sight -- you cannot see parts of the maze your avatar (the '@') could not +them on screen for the user to explore, complete with Line Of Sight +\- you cannot see parts of the maze your avatar (the `@`) could not have seen. -The maze files will be interpreted with spaces ' ' as gaps, tilde -'~' symbols (if any) as exits (which get represented as a NetHack -style '<' once loaded), and any other characters as walls. +The maze files will be interpreted with spaces `' '` as gaps, tilde +`~` symbols (if any) as exits (which get represented as a +[NetHack](https://www.nethack.org) style `<` once loaded), and any other +characters as walls. -Feed the program its own source for a default maze. Running it with -no command line parameters will do this. In a nice symmetry, the -character constant '~' that recognises exits to input mazes itself -forms the exit to the default maze. Another maze, 'maze1' has also -been provided. This maze is 255x255, about the largest maze supported, -for the particularaly insane maze explorers out there. +Feed the program its own source for a default maze. Running it with no command +line parameters will do this. In a nice symmetry, the character constant `~` +that recognises exits to input mazes itself forms the exit to the default maze. +Another maze, [arachnid.txt](arachnid.txt) has also been provided. This maze is +255x255, about the largest maze supported, for the particularly insane maze +explorers out there. -Usage: +### Usage ```sh ./arachnid [mazefile] ``` -You can explore the maze using the w,a,s, and d keys. +You can explore the maze using the `w`,`a`,`s`, and `d` keys. ## Copyright and CC BY-SA 4.0 License: diff --git a/2004/arachnid/arachnid.info b/2004/arachnid/arachnid.txt similarity index 100% rename from 2004/arachnid/arachnid.info rename to 2004/arachnid/arachnid.txt diff --git a/2004/burley/README.md b/2004/burley/README.md index 2caacff8c..c34917e50 100644 --- a/2004/burley/README.md +++ b/2004/burley/README.md @@ -1,9 +1,7 @@ # Best Calculated Risk - Brent Burley - 500 S. Buena Vista St. - Burbank, CA 91521 - USA +Brent Burley +US ## To build: @@ -37,29 +35,34 @@ echo "Do or do not. There is no try." ## Judges' remarks: -This is a draw poker program. You start with $100. Input alternates -between your bet and which cards to keep. Example: +This is a [draw poker](https://en.wikipedia.org/wiki/Draw_poker) program. You +start with $100. Input alternates between your bet and which cards to keep. +Example: - 5 <== you enter a bet of $5 (defaults to $1) - J Q J 9 5 <== your hand is Jack of Clubs, Queen of Hearts, - C H D S C Jack of Diamonds, 9 of Spades, 5 of Clubs - 123 <== you enter which cards you want to keep - (enter 0 to 5 digits between 1 and 5) - J Q J J Q <== your new hand is Jack of Clubs, Queen of Hearts, - C H D S C Jack of Diamonds, Jack of Spaces, Queen of clubs - $145 (45) <== Your new balance is now $145. You had a Full House - so your payoff is 9 times your bet == 45 +``` +5 <== you enter a bet of $5 (defaults to $1) +J Q J 9 5 <== your hand is Jack of Clubs, Queen of Hearts, +C H D S C Jack of Diamonds, 9 of Spades, 5 of Clubs +123 <== you enter which cards you want to keep + (enter 0 to 5 digits between 1 and 5) +J Q J J Q <== your new hand is Jack of Clubs, Queen of Hearts, +C H D S C Jack of Diamonds, Jack of Spaces, Queen of clubs +$145 (45) <== Your new balance is now $145. You had a Full House + so your payoff is 9 times your bet == 45 +``` The payout is according to "Vegas rules": - Straight Flush 50 times your bet - Four of a Kind 25 times your bet - Full House 9 times your bet - Flush 6 times your bet - Straight 4 times your bet - 3 of a Kind 3 times your bet - 2 Pair 2 times your bet - Jacks or Better 1 times your bet +``` +Straight Flush 50 times your bet +Four of a Kind 25 times your bet +Full House 9 times your bet +Flush 6 times your bet +Straight 4 times your bet +3 of a Kind 3 times your bet +2 Pair 2 times your bet +Jacks or Better 1 times your bet +``` The program allows you to go into debt. However I'm sure you would never control-C kill the program just because you got behind, right? @@ -69,16 +72,16 @@ to leave even when you are ahead. :-) Can you figure out a winning betting "strategy"? Then can you modify the program so this "strategy" no longer works? -Notice the clever use of setjmp() and longjmp() calls. Can you keep -track of what state is being saved and restored? +Notice the clever use of `setjmp()` and `longjmp()` calls. Can you keep track +of what state is being saved and restored? -## Author's remarks +## Author's remarks: This program plays draw poker. What is unusual about it is that it is written as a single statement -- count the semicolons! (OK, there are really three statements if you count the variable declarations.) To keep things simple, I have avoided the C preprocessor and tricky -statements such as "if", "for", "do", "while", "switch", and "goto". +statements such as `if`, `for`, `do`, `while`, `switch`, and `goto`. ## Copyright and CC BY-SA 4.0 License: diff --git a/2004/gavare/.gitignore b/2004/gavare/.gitignore index 723be8180..d158d2e8d 100644 --- a/2004/gavare/.gitignore +++ b/2004/gavare/.gitignore @@ -1,2 +1,3 @@ gavare ioccc_ray.ppm +gavare.r3 diff --git a/2004/gavare/Makefile b/2004/gavare/Makefile index b663d8425..f256bf86e 100644 --- a/2004/gavare/Makefile +++ b/2004/gavare/Makefile @@ -114,8 +114,8 @@ OBJ= ${PROG}.o DATA= TARGET= ${PROG} # -ALT_OBJ= -ALT_TARGET= +ALT_OBJ= ${PROG}.r3.o +ALT_TARGET= ${PROG}.r3 ################# diff --git a/2004/gavare/README.md b/2004/gavare/README.md index 8505d6be3..cb525da73 100644 --- a/2004/gavare/README.md +++ b/2004/gavare/README.md @@ -1,11 +1,8 @@ # Best Use of Light and Spheres - Anders Gavare - Gibraltargatan 82-156 - SE-412 79 Gothenburg - Sweden - - http://www.mdstud.chalmers.se/~md1gavan/ +Anders Gavare +Sweden + ## To build: @@ -25,15 +22,31 @@ make ./gavare > ioccc_ray.ppm ``` +### Alternate code: + +The author provided [on their web page for the +entry](https://gavare.se/ioccc/ioccc_gavare.c.html) an unobfuscated version that was used +during development, which we have included in the file +[gavare.r3.c](gavare.r3.c). To compile, try: + + +```sh +make alt +``` + +Use `gavare.r3` as you would `gavare` above. + + + ## Judges' remarks: For users of systems that distinguish between text and binary mode (you know who you are), add a library call that specifies binary mode -for stdout as the first statement of main(), -or use freopen("ioccc_ray.ppm", "wb", stdout) and do not use redirection. +for stdout as the first statement of `main()`, +or use `freopen("ioccc_ray.ppm", "wb", stdout);` and do not use redirection. A freely distributable command-line version of Microsoft Visual C -exhibits an optimizer bug when compiling this entry. Disable /Og for +exhibits an optimizer bug when compiling this entry. Disable `/Og` for best results. The judges were able to figure out how to control position @@ -51,8 +64,8 @@ directives. The program is a small ray-tracer. The first line of the source code may be modified if you want the resulting image to be of some other resolution -than the predefined. The 'A' value is an anti-alias factor. Setting it to -1 disables the anti-aliasing feature (this makes the output look bad), but +than the predefined. The `A` value is an anti-alias factor. Setting it to +`1` disables the anti-aliasing feature (this makes the output look bad), but setting it too high makes the trace take a lot more time to complete. The ppm image can then be viewed using an image viewer of your own choice. @@ -60,18 +73,18 @@ The ppm image can then be viewed using an image viewer of your own choice. so be patient.) I am very much aware about the fact that I'm breaking the guidelines. For -example, the word 'int' is a reserved word and therefore all variable +example, the word `int` is a reserved word and therefore all variable declarations are implicit. There will no doubt be _lots_ of warnings, no matter which compiler is used. Still, the source code should be word- -length-independent and endianess-independent. +length-independent and endianness-independent. + +### Humor - Another reason for writing code without using reserved words is that many text editors will make all reserved words turn BOLD when printed on paper. Since I care for the global environment, we shouldn't waste any more laser toner, or ink, than necessary. Everyone should write C code -with no reserved words, and our world will be a better place. - +with no reserved words, and our world will be a better place. ## Copyright and CC BY-SA 4.0 License: diff --git a/2004/gavare/gavare.r3.c b/2004/gavare/gavare.r3.c new file mode 100644 index 000000000..0b8ae3e2c --- /dev/null +++ b/2004/gavare/gavare.r3.c @@ -0,0 +1,445 @@ + +/* + * IOCCC Raytracer by Anders Gavare. + * + * The raytracer was one of the winners of the 17th IOCCC. + * + * NOTE: This is the UNOBFUSCATED version of the raytracer I used + * during development, not the actual entry sent to the contest. + * + * + * How to build: + * cc gavare.r3.c -o gavare.r3 (plus optimization flags) + * + * How to run: + * ./gavare.r3 > ray.ppm + * or + * ./gavare.r3 | xv - + */ + +xsize = 1024; +ysize = 768; +An = 3; + +camera_X = 0; +camera_Y = -10; +camera_Z = -7; + +scale = 1296; +RootOfScale = 36; +maxcolor = 255; + +MaxDepth=9; +_=1<<15; + +/* +double sphere_x[44] = { + -15,-15,-15,-15, // I + -8,-8,-10,-6,-10,-6, // O + -1,-1, 1,1, // C + 6, 6, 8,8, // C + 13,13,15,15, // C + -11,-11,-11,-11,-9,-9,-7,-7, // r + 0,0,-2,-2,-2,2,2,2, // a + 7,7,9,9,11,11, // y + }; +double sphere_z[44] = { + 3,0,-3,-6, // I + -6, 3,0,0,-3,-3, // O + 0,-3,-6, 3, // C + 0,-3,-6, 3, // C + 0,-3,-6, 3, // C + -11,-13,-15,-17,-11,-15,-13,-17, // r + -11,-15,-13,-15,-17,-13,-15,-17, // a + -11,-13,-15,-17,-11,-13, // y + }; +*/ + +/* Common return variable: */ +return_var; +return_var2; +return_var3; +return_var4; + + +get_sphere_coordinates(b) +{ + return_var = "1111886:6:??AAFFHHMMOO55557799@@>>>BBBGGIIKK"[b]-64; + return_var3 = "C@=::C@@==@=:C@=:C@=:C531/513/5131/31/531/53"[b]-64; + +/* return_var = sphere_x[b]; */ + return_var2 = b<22? 9 : 0; +/* return_var3 = sphere_z[b]; */ + return_var4 = 2; +} + + +/* sqroot(x) returns the square root of x in return_var */ +sqroot_sub(x, mask, guess) +{ + mask? + ( + guess ^= mask, + guess*guess > x ? + ( guess ^= mask ) + : + 0, + sqroot_sub(x, mask/2, guess) + ) + : + ( return_var = guess ); +} + + +sqroot(x) +{ + sqroot_sub(x, _, 0); +} + + +/* + * hit_sphere(): + * + * returns where on a sphere we hit + * Returns distance in hit_sphere_q. (Negative return + * value if we didn't hit anything.) + */ +hit_sphere_q; +hit_sphere(objnr, x, y, z, + dx, dy, dz, + a, b) +{ + get_sphere_coordinates(objnr); + x -= return_var*scale; + y -= return_var2*scale; + z -= return_var3*scale; + + /* + * Solve the following equation: + * + * q^2 (dx^2+dy^2+dz^2) + q * 2(x*dx+y*dy+z*dz) + * + x^2+y^2+z^2 - r^2 = 0 + * + * We assume that |dx,dy,dz| is 1. + * + * q^2 + a q + b = 0 + * + * The solution is (of course) + * + * q = -a/2 +- sqrt(a^2/4 - b) + */ + + b = x*x/scale+y*y/scale+z*z/scale-return_var4*return_var4*scale; + + /* a = 2*(...), and then divide by -2 */ + a = -x*dx/scale-y*dy/scale-z*dz/scale; + + hit_sphere_q = + ( + (b = a*a/scale - b) >= 0 ? + ( +/* b = scale*sqrt((double)b/(double)scale), */ +/* sqroot(b*scale), */ + +/* sqroot_sub(b, _, 0), + b = return_var * RootOfScale, +*/ + sqroot_sub(b*scale, _, 0), + b = return_var, + + /* + * Return the lowest q (a+b or a-b) which is more + * than 0. Return negative if neither + * a+b or a-b is more than 0. + */ + + a + (a>b? -b : b) + ) + : + -1.0 + ); +} + + +/* + * find_closest(): + * + * find_closest() scans objects and returns an index + * to the object which was closest (has the lowest 'q'). + * x,y,z,dx,dy,dz are scaled. + * find_closest_i is the index number of the found object, + * -1 if none was found. find_closest_q is the distance + * (scaled). + */ +find_closest_i; /* index ("sphere number") */ +find_closest_q; /* distance (scaled) */ +find_closest(objnr, x, y, z, + dx, dy, dz, notindex) +{ + /* Initialize find_closest_i on first call: */ + find_closest_i = + !objnr ? -1 : find_closest_i; + + objnr < 44 ? + ( + hit_sphere(objnr, x,y,z, dx,dy,dz, 0,0), + (hit_sphere_q > 0 && objnr!=notindex && + (hit_sphere_q0 && find_closest_i >= 0? + ( + /* find_closest_i and _q are the object + number and distance of the object we + hit. */ + + orig_x += dir_x*find_closest_q/scale, + orig_y += dir_y*find_closest_q/scale, + orig_z += dir_z*find_closest_q/scale, + + /* + * Calculate color (diffuse light): + * (Note: use nZ as a temp variable while + * calculating nY) + */ + get_sphere_coordinates(find_closest_i), + nX = orig_x - return_var*scale, + nY = orig_y - return_var2*scale, + nZ = orig_z - return_var3*scale, + + tmpcol = (-2*nX -2*nY + nZ) / 3, /* sqrt(9), */ + /* Set return_var to the length of the normal + vector (in this case the sphere radius) */ +/* return_var = sqrt(nX*nX + nY*nY +nZ*nZ), */ + sqroot(nX*nX + nY*nY +nZ*nZ), +// return_var = return_var4*scale, + /* divide by return_var to get the color */ +// tmpcol = return_var!=0? tmpcol*scale/return_var : 0, + tmpcol /= return_var4, + + /* color is now -1..1 */ + tmpcol *= tmpcol, /* square the color 1..-1 => 1..1 */ + tmpcol *= 200, + tmpcol /= (scale*scale), +/* tmpcol += 5, */ + + closest_i_saved = find_closest_i, + + /* Mirror: out = in - 2*(-normal)*cos v + where v is the angle between in and + -normal */ + + /* -normal: (normalized to len=1.0) */ +/* return_var = sqrt(nX*nX + nY*nY + nZ*nZ), */ + return_var!=0? + ( + nX = -nX * scale / return_var, + nY = -nY * scale / return_var, + nZ = -nZ * scale / return_var + ) : 0, + + /* use return_var as a temp variable, + calculate cosinus between the vectors */ + return_var = (dir_x*nX + dir_y*nY + dir_z*nZ)/scale, +/* + dir_x -= 2 * nX * return_var / scale, + dir_y -= 2 * nY * return_var / scale, + dir_z -= 2 * nZ * return_var / scale, +*/ + dir_x -= nX * return_var / (scale/2), + dir_y -= nY * return_var / (scale/2), + dir_z -= nZ * return_var / (scale/2), + + trace_ray(orig_x, orig_y, orig_z, + dir_x, dir_y, dir_z, + depth-1, find_closest_i, 0,0), + + trace_ray_R /= 2, + trace_ray_G /= 2, + trace_ray_B /= 2, +/* + closest_i_saved &= 7, + !closest_i_saved? (closest_i_saved++) : 0, +*/ +/* + closest_i_saved = closest_i_saved<4? closest_i_saved+1 : 7, +*/ +/* + tvinga gr\E5skalor: closest_i_saved = 7, +*/ +closest_i_saved = closest_i_saved<22? 7 : + ( + closest_i_saved<30 ? 1 : + ( + closest_i_saved<38 ? 2 : + ( + closest_i_saved<44 ? 4 : + ( + closest_i_saved == 44 ? 6 : + 3 + ) + ) + ) + ), + + trace_ray_R += closest_i_saved & 1 ? tmpcol : 0, + trace_ray_G += closest_i_saved & 2 ? tmpcol : 0, + trace_ray_B += closest_i_saved & 4 ? tmpcol : 0 + ) + : + ( + /* If we didn't hit anything, set the color anyway: */ + + depth==MaxDepth? /* True if this is a ray originating + from the camera */ + ( + orig_z += 2, + dir_z = orig_z > 0? orig_z / 8 : orig_z / 20 + ) + : 0, + + /* + * Colors according to Horizon_1 in gimp: + * At top of sky: 13,92,146 (light blue) + * At bottom sky: 255,255,255 (white) + * Top of ground: 213,168,111 (light brown) + * Bottom of ground: 103, 55, 26 (brown) + */ + + dir_z > 0? + ( + trace_ray_B = dir_z * dir_z / scale, + trace_ray_R = 255 - 250 * trace_ray_B / scale, + trace_ray_G = 255 - 150 * trace_ray_B / scale, + trace_ray_B = 255 - 100 * trace_ray_B / scale + ) + : + ( + trace_ray_B = dir_z * dir_z / scale, + trace_ray_B < scale/5? + ( + trace_ray_R = 255 - 210 * trace_ray_B / scale, + trace_ray_G = 255 - 435 * trace_ray_B / scale, + trace_ray_B = 255 - 720 * trace_ray_B / scale + ) + : + ( + trace_ray_B -= scale/5, + trace_ray_R = 213 - 110 * trace_ray_B / scale, + trace_ray_G = 168 - 113 * trace_ray_B / scale, + trace_ray_B = 111 - 85 * trace_ray_B / scale + ) + ), + + depth!=MaxDepth? + ( + trace_ray_R /= 2, + trace_ray_G /= 2, + trace_ray_B /= 2 + ) + : 0 + ); + + trace_ray_R = trace_ray_R<0? 0 : trace_ray_R>maxcolor? maxcolor: trace_ray_R; + trace_ray_G = trace_ray_G<0? 0 : trace_ray_G>maxcolor? maxcolor : trace_ray_G; + trace_ray_B = trace_ray_B<0? 0 : trace_ray_B>maxcolor? maxcolor : trace_ray_B; +} + + +/* + * do_pixels_in_line(): + * + * the horizontal "for loop" + */ +R; G; B; +dpil_helper(x,y, a,b) +{ + trace_ray( + scale*camera_X + scale*40*(An*x+a)/xsize/An - scale*20, + scale*camera_Y, + scale*camera_Z - scale*30*(An*y+b)/ysize/An + scale*15, + 0, scale, 0, MaxDepth, -1, 0,0); + + R += trace_ray_R; + G += trace_ray_G; + B += trace_ray_B; + + ++a for +QEMU ([Fabrice Bellard](/winners.html#Fabrice_Bellard) is an IOCCC 2001 winner), +but your experience will be limited (replace `-DK=0` with `-DK=1` in the +[Makefile](Makefile), and you will have to move the mouse to trigger the initial +screen update). The judges were able to write a few more programs to run on this OS What are the limitations for such programs? + What you can do and what you cannot do in such programs? -The program called "prim", written by the judges, -computes and prints prime numbers. +The program called `prim`, written by the judges, computes and prints prime +numbers. ## Author's remarks: This is a 32-bit multitasking operating system for x86 computers, with GUI and filesystem, support for loading and executing user -applications in elf binary format, with ps2 mouse and keyboard drivers, +applications in elf binary format, with PS/2 mouse and keyboard drivers, and vesa graphics. And a command shell. And an application - a simple text-file viewer. @@ -107,16 +108,16 @@ which is partially defined by the OS, and partially for the application's own use. The program compiles into a tool to build a kernel image, -so having built the program, the makefile will run it, -piping the output into a file called 'kernel'. -The makefile will then proceed to build a root filesystem image. +so having built the program, the [Makefile](Makefile) will run it, +piping the output into a file called `kernel`. +The Makefile will then proceed to build a root filesystem image. This involves rebuilding the program with different compiler flags, then building a tar file containing the resulting programs (the filesystem format supported by the OS is the tar-file format). -For further usage information see 'gavin_install.txt'. +For further usage information see [gavin.md](gavin.md). -The filenames 'vi' and 'sh' are significant, and should not be changed. +The filenames `vi` and `sh` are significant, and should not be changed. ### Known 'features' @@ -127,40 +128,38 @@ it will reappear on the right, and vice-versa. If it goes off the top or bottom, it will go and corrupt some memory. The file system is kinda optimistic about matching names, so, -for example if you type the command 'shell' into a command-line -it will execute the program 'sh' - close enough a match for it. +for example if you type the command `shell` into a command-line +it will execute the program `sh` - close enough a match for it. -The elf binaries are not loaded at the correct address, -and their entry point must be the start address of the text segment. +The ELF binaries are not loaded at the correct address, and their entry point +must be the start address of the text segment. The keyboard driver can cope with the basic alpha-numeric keys, -but gets confused by fancy things like 'shift' or 'backspace'. +but gets confused by fancy things like `shift` or `backspace`. -In the text-file viewer, 'vi', the up/down and pgup/pgdn keys +In the text-file viewer, `vi`, the up/down and PgUp/PgDn keys scroll up or down by one line. There is nothing to stop you -[from] scrolling above the top of the file, and pressing any -other keys may have an undefined effect. +from scrolling above the top of the file, and pressing any +other keys might have an undefined effect. -The x86 is bootstrapped into 32bit mode in 6 instructions, -with 4 more to set up data/stack segments and a stack-pointer -to allow C code to be run. On top of this there are also about -a dozen instructions to switch the video card into graphics mode. -All in all, a relatively tiny number of instructions next to -the size of the C program. Also, the string is mostly composed -of data - a Linux-esque kernel header for the bootloader, -protected mode descriptor tables, keyboard maps, etc. -(I should also mention that it contains mini functions -to perform an x86 'in' and 'out' instruction - to allow -the keyboard & mouse to be driven from C code). +The x86 is bootstrapped into 32bit mode in 6 instructions, with 4 more to set up +data/stack segments and a stack-pointer to allow C code to be run. On top of +this there are also about a dozen instructions to switch the video card into +graphics mode. All in all, a relatively tiny number of instructions next to the +size of the C program. Also, the string is mostly composed of data - a +Linux-esque kernel header for the bootloader, protected mode descriptor tables, +keyboard maps, etc. (I should also mention that it contains mini functions to +perform an x86 `in` and `out` instruction - to allow the keyboard & mouse to be +driven from C code). -Porting to another architecture should be relatively easy* - +Porting to another architecture should be relatively easy\* - the string simply needs be replaced with one containing data & code suitable for the new target platform. -Accesses to data in the string are made relative to the define 'V', -so these may need updating as appropriate (0x90200 is the address +Accesses to data in the string are made relative to the define `V`, +so these may need updating as appropriate (`0x90200` is the address at which a Linux bootloader loads an x86 kernel image). -* ;-) +\* ;-) ## Copyright and CC BY-SA 4.0 License: diff --git a/2004/gavin/gavin.md b/2004/gavin/gavin.md new file mode 100644 index 000000000..9ab300ec0 --- /dev/null +++ b/2004/gavin/gavin.md @@ -0,0 +1,44 @@ +# Usage + +1. First, build the kernel and filesystem (just `make`). In short, you need to +build this on an x86 Linux machine. If you wish to try to compile on an OS +other than Linux you may need modify the [Makefile](Makefile) to compile `sh` +using a cross-compiler that produces ELF binaries - i.e. a cross-compiler +targeting x86 Linux. In short, you need to build this on an x86 Linux machine. + +2) Next, find a suitable machine to run the OS on. It should be perfectly safe, +and since it does not directly attempt to access any hard disk drives (only a +ramdisk loaded by the bootloader) it should do no damage to your existing setup, +BUT I ACCEPT NO LIABILITY FOR ANY DAMAGE DONE BY THIS PROGRAM. Run it at your +own risk. The OS has been tested on half a dozen machines or so, and worked on +all but one. The failure came in the form of the machine rebooting itself +midway through loading the OS, with no nasty side-effects. + + Hardware requirements - i386 or better processor, but the GUI is + surprisingly power-hungry, so I would recommend a fast P3 or P4 processor + (has been tested on P3/P4/Athlon machines). Minimum RAM is something like + 32MB. PS/2 mouse & keyboard required - no USB I'm afraid, and the keyboard + map is for a UK keyboard. Uses Vesa VBE 3.0, so should work on any modern + graphics card (has been tested on NVIDIA, Matrox, and SiS cards). + +3. Now you need to setup a bootloader to load the OS. If you have a system +using a lilo bootloader you can simply add the OS to your boot menu. Just add +appropriate `image=` and `initrd=` lines to your `/etc/lilo.conf`, pointing at +`kernel` and `fs.tar` respectively (as built by make earlier), then run `lilo`. +If you do not wish modify your lilo setup, one easy option is to get yourself a +grub boot disk image, and follow the instructions for grub below - Debian users +can simply run`apt-get install grub-disk` to get themselves a grub boot disk. + + If you run grub, then at the boot menu simply hit `c` to get a console, then + type `kernel=(hd0,0)//kernel` (substituting appropriate hard + drive/partition numbers & path, or using `(fd0)` to load a kernel on the + floppy), then `initrd=(hd0,0)//fs.tar`, and finally `boot`. + +4. Assuming the OS has booted, what can you do now? Well, start by trying `sh`, +to open another shell. Then, try `vi gavin.c` to open up the OS source in a +text file viewer (up/down or PgUp/PgDn to scroll). Note that the provided +applications, `sh` and `vi` both have windows of the same size, and that open in +the top left corner of the screen, so you may need drag the windows around a bit +to tell them apart. + +5. To shut down - just hit the power button. :-) diff --git a/2004/gavin/gavin_install.txt b/2004/gavin/gavin_install.txt deleted file mode 100644 index 6be70899e..000000000 --- a/2004/gavin/gavin_install.txt +++ /dev/null @@ -1,16 +0,0 @@ -1) First, build the kernel and filesystem (just 'make'). In short, you need to build this on an x86 Linux machine. If you wish to try to compile on an OS other than Linux you may need modify the makefile to compile 'sh' using a cross-compiler that produces elf binaries - i.e. a cross-compiler targeting x86 Linux. In short, you need to build this on an x86 Linux machine. - -2) Next, find a suitable machine to run the OS on. It should be perfectly safe, and since it does not directly attempt to access any hard disk drives (only a ramdisk loaded by the bootloader) it should do no damage to your existing setup, BUT I ACCEPT NO LIABILITY FOR ANY DAMAGE DONE BY THIS PROGRAM. Run it at your own risk. The OS has been tested on half a dozen machines or so, and worked on all but one. The failure came in the form of the machine rebooting itself midway through loading the OS, with no nasty side-effects. - -Hardware requirements - i386 or better processor, but the GUI is surprisingly power-hungry, so I would recommend a fast p3 or p4 processor (has been tested on p3/p4/athlon machines). Minimum RAM is something like 32MB. PS2 mouse & keyboard required - no USB I'm afraid, and the keyboard map is for a UK keyboard. Uses Vesa VBE 3.0, so should work on any modern graphics card (has been tested on Nvidia, Matrox, and SiS cards). - -3) Now you need to setup a bootloader to load the OS. If you have a system using a lilo bootloader you can simply add the OS to your boot menu. Just add appropriate "image=" and "initrd=" lines to your /etc/lilo.conf, pointing at 'kernel' and 'fs.tar' respectively (as built by make earlier), then run lilo. If you do not wish modify your lilo setup, one easy option is to get yourself a grub bootdisk image, and follow the instructions for grub below - debian users can simple "apt-get install grub-disk" to get themselves a grub bootdisk. - -If you run grub, then at the boot menu simply hit 'c' to get a console, then type "kernel=(hd0,0)//kernel" (substituting appropriate harddrive/partition numbers & path, or using "(fd0)" to load a kernel on the floppy), then "initrd=(hd0,0)//fs.tar", and finally "boot". - -4) Assuming the OS has booted, what can you do now? Well, start by trying "sh", to open another shell. Then, try "vi prog.c" (although this file may have been re-named...), to open up the OS source in a text file viewer (up/down or pgup/pgdown to scroll). [Note that the provided applications, 'sh' and 'vi' both have windows of the same size, and that open in the top left corner of the screen, so you may need drag the windows around a bit to tell them apart.] - -5) To shut down - just hit the power button. :-) - - - diff --git a/2004/gavin/prim b/2004/gavin/prim old mode 100644 new mode 100755 diff --git a/2004/hibachi/README.md b/2004/hibachi/README.md index 43662dcd6..3c641d945 100644 --- a/2004/hibachi/README.md +++ b/2004/hibachi/README.md @@ -1,12 +1,8 @@ # Best Abuse of the Guidelines - Anthony Howe - Snert - 42 av. Isola Bella - 06400 Cannes - France - - http://www.snert.com/ +Anthony Howe +Canada + ## To build: @@ -17,45 +13,52 @@ make ## To run: ```sh -cd build; ./hibachi-start.sh +cd build; ./hibachi-start.sh & ``` ## Try: ```sh -cd build; ./hibachi-start.sh +cd build; ./hibachi-start.sh & ``` -Then use your web browser to visit http://localhost:8008/ +Then use your web browser to visit `http://localhost:8008/`. When you're +finished make sure to kill `hibachi`. + +NOTE: you must be in the `build` directory when running `hibachi` for this to +work. ## Judges' remarks: -This entry violates the guidelines in so many ways! We are not -exactly sure how many org's will be upset with this entry, but we -are considering starting an IOCCC standards body just to reign in -the likes Mr Howe. +This entry violates the [guidelines](/2004/guidelines.txt) in so many ways! We +are not exactly sure how many organisations will be upset with this entry, but +we are considering starting an IOCCC standards body just to reign in the likes +of Mr Howe. -This entry also has the dubious honour of being the only one to have -been submitted with its own ./configure script. +This entry also has the dubious honour of being the only one to have been +submitted with its own [configure](build/configure) script. + +NOTE: the author states there is a tarball `hibachi.tgz` but this was extracted +so the file does not exist here. ## Author's remarks: ### README.TXT (Feb 2004) -Hibachi is a simple, small, and (probably) very secure web server. +`Hibachi` is a simple, small, and (probably) very secure web server. -There is a `hibachi.tgz' file that unpacks several support +There is a `hibachi.tgz` file that unpacks several support files and a sub-directory tree containing the documentation and examples. It can be viewed by: - tar -zxf hibachi.tgz - lynx hibachi/localhost/index.html +```sh +tar -zxf hibachi.tgz +lynx hibachi/localhost/index.html +``` -Or once Hibachi is running, use a web browser, preferably one that +Or once `Hibachi` is running, use a web browser, preferably one that supports images and JavaScript, to view the documentation and try -some of the CGI examples: - - http://localhost:8008/ +some of the CGI examples, visit: http://localhost:8008/. ### Building @@ -71,7 +74,7 @@ For Linux (older): ```sh gcc -DSHUT_WR=1 -o hibachi hibachi.c -`` +``` For SunOS: @@ -79,12 +82,12 @@ For SunOS: gcc -o hibachi hibachi.c -lnsl -lsocket ``` -Since some systems place socket and network functions into other -libraries, a GNU autoconf ./configure script has been provided to -figure out the necessary link libraries, to verify all the -necessary headers and functions are present, and setup the #! -paths for the CGI examples. In which case the preferred build -commands are: +Since some systems place socket and network functions into other libraries, a +[GNU autoconf](https://en.wikipedia.org/wiki/Autoconf) +[configure](https://en.wikipedia.org/wiki/Configure_script) script has been +provided to figure out the necessary link libraries, to verify all the necessary +headers and functions are present, and setup the `#!` paths for the CGI +examples. In which case the preferred build commands are: ``` ./configure [--enable-port=number] @@ -94,6 +97,7 @@ make To start the server on the default port (8008): ```sh +cd build; ./hibachi-start.sh & ``` @@ -113,31 +117,33 @@ kill %1 * Supports virtual hosts. -* Supports all MIME types. +* Supports all [MIME](https://en.wikipedia.org/wiki/MIME) types. -* Supports Common Gateway Interface (CGI) scripts and programs. +* Supports [Common Gateway Interface +(CGI)](https://en.wikipedia.org/wiki/Common_Gateway_Interface) scripts and programs. * Supports multiple index.* file types: - index.htm, index.html, index.php, index.pl, - index.sh, index.rb, index.py + index.htm, index.html, index.php, index.pl, index.sh, index.rb, index.py -* Supports subset of RFC 2616 HTTP/1.1 methods: +* Supports subset of [RFC 2616](https://datatracker.ietf.org/doc/html/rfc2616) +[HTTP](https://en.wikipedia.org/wiki/HTTP)/1.1 methods: - GET, HEAD, and POST + `GET`, `HEAD`, and `POST` * Simple & straight forward configuration using environment variables. -* Portability across Unix-like environments, such as: - - Cygwin, FreeBSD, Linux, SunOS. +* Portability across Unix-like environments, such as: Cygwin, FreeBSD, Linux, +SunOS. * Known to work with Lynx, Mozilla, Opera, and Internet Explorer web browsers. -* Is a dedicated process-forking server that does not use inetd. +* Is a dedicated process-forking server that does not use +[inetd](https://en.wikipedia.org/wiki/Inetd). -* Is secure against relative path file snooping. +* Is secure against [relative path file +snooping](https://cwe.mitre.org/data/definitions/23.html). * Is secure against directory searches. @@ -147,27 +153,31 @@ kill %1 1940 bytes long by IOCCC 2004 rules, ~6KB compiled & stripped for FreeBSD. -* Superior & smaller than micro_httpd from http://www.acme.com/ +* Superior & smaller than +[micro_httpd](http://www.acme.com/software/micro_httpd/) from . * And has a really cool tongue-in-cheek animated logo too. ### Comments -* This code is properly indented using the One True Brace style. +* This code is properly indented using the [One True Brace +style](https://wiki.c2.com/?OneTrueBraceStyle). -* HTTP/1.0 200 OK == HTTP/1.1 200 OK CRLF Connection: close ? +* `HTTP/1.0 200 OK` == `HTTP/1.1 200 OK CRLF Connection: close` ? -* getenv() == putenv() ? +* `getenv()` == `putenv()` ? -* Hibachi can serve www.ioccc.org. +* `Hibachi` can serve [www.ioccc.org](https://www.ioccc.org). * Commented spoiler available. ### Known Issues -* The "links" text browser does not support RFC 2616 section 7.2.1 +* The [links][1] text browser does not support RFC 2616 section 7.2.1 paragraph 3 sentence 2, and so fails to display responses from - hibachi. + `hibachi`. + +[1]: https://en.wikipedia.org/wiki/Links_(web_browser) ### Suggested IOCCC Categories diff --git a/2004/hoyle/README.md b/2004/hoyle/README.md index 425b7b88c..527a040e2 100644 --- a/2004/hoyle/README.md +++ b/2004/hoyle/README.md @@ -1,11 +1,8 @@ # Most Functional Output - Jonathan Hoyle - 162 Burwyck Park - Saline, MI 48176 - USA - - http://www.jonhoyle.com +Jonathan Hoyle +US + ## To build: @@ -29,8 +26,8 @@ make ### Alternate code -An alternate version of this entry, `hoyle.alt.c`, is provided. This alternate code -has a missing newline and used a non-standard tab stop size. +An alternate version of this entry, [hoyle.alt.c](hoyle.alt.c), is provided. +This alternate code has a missing newline and used a non-standard tab stop size. To compile this alternate version: @@ -40,29 +37,29 @@ make alt Use `hoyle.alt.c` as you would `hoyle` above. -## Judges' remarks +## Judges' remarks: This obfuscation functions at several levels. Note the clever -use of use of #defines. The do(if,else) #define, for example, +use of use of `#define`s. The `#define do(if,else)`, for example, is delightful. The code itself contains a bunch of curves designed to throw you off axis. :-) -## Author's remarks +## Author's remarks: -This application graphs polynomials on a standard Cartesian coordinate -system. Polynomials of the form ax^0 + bx^1 + cx^2 + ... are graphed by -passing the coefficients a, b, c, etc. as double precision arguments. -It allows up to 8 parameters (thus up to x^7). +This application graphs polynomials on a standard Cartesian coordinate system. +Polynomials of the form `ax^0 + bx^1 + cx^2 +` ... are graphed by passing the +coefficients `a`, `b`, `c`, etc. as double precision arguments. It allows up to +8 parameters (thus up to `x^7`). -Points of note: +### Points of note: -- the x axis goes from -32 to +31 -- the y axis auto scales! -- up to 8 coefficients may be passed in +- the [x axis](https://mathworld.wolfram.com/x-Axis.html) goes from `-32` to `+31` +- the [y axis](https://mathworld.wolfram.com/y-Axis.html) auto scales! +- up to 8 [coefficients](https://en.wikipedia.org/wiki/Coefficient) may be passed in - the graph will determine direction and use slashes and - dashes rather than simple block X's. + dashes rather than simple block `X`s. -For example, ta graph y = x^2: +For example, ta graph `y = x^2`: ```sh ./hoyle 0 0 1 @@ -74,7 +71,7 @@ Note that: ./hoyle 0 0 2 ``` -will produce the same graph, since the y-axis is auto scaling. +will produce the same graph, since the `y-axis` is auto scaling. ## Copyright and CC BY-SA 4.0 License: diff --git a/2004/jdalbec/README.md b/2004/jdalbec/README.md index 9e4da749e..db4602e8c 100644 --- a/2004/jdalbec/README.md +++ b/2004/jdalbec/README.md @@ -1,11 +1,8 @@ # Best Abuse of the Periodic Table - John Dalbec - 20 Squire's Ct. - Canfield OH 44406 - USA - - http://cc.ysu.edu/~jpdalbec/ +John Dalbec +US + ## To build: @@ -37,47 +34,52 @@ it's the first atomic fission we've seen in the IOCCC. It's elementary! -See http://mathworld.wolfram.com/LookandSaySequence.html, -http://mathworld.wolfram.com/CosmologicalTheorem.html, -and the references listed there. +See and + and the references +listed there. Go read the web pages and come back. -This program implements the look-and-say sequence with the -added feature that each "decay product" is automatically split -into its constituent "elements" separated by spaces. Furthermore, -arguments passed to the program are treated as separate elements -for the purpose of computing further decay products. (Compare -the output of "prog 1", "prog 11", and "prog 1 1".) This -allows output lines from the program to be passed back to the +This program implements the [look-and-say sequence (one of the above listed +links)](https://mathworld.wolfram.com/LookandSaySequence.html) with the added +feature that each "decay product" is automatically split into its constituent +"elements" separated by spaces. Furthermore, arguments passed to the program +are treated as separate elements for the purpose of computing further decay +products. (Compare the output of `./jdalbec 1`, `./jdalbec 11`, and `./jdalbec +1 1`.) This allows output lines from the program to be passed back to the program as input (minus the initial generation number). -The common elements are listed in CosmologicalTheorem.html. -The non-primordial transuranic elements are the isotopes of -Neptunium and Plutonium. Isotopes of a given element differ -only in the last digit. Four common elements could also be -written as isotopes of these two elements: He=Np(2), Li=Pu(2), -Ta=Np(3), W=Pu(3). To get other isotopes, just change the -last digit to a number greater than 3. +The common elements are listed in +[CosmologicalTheorem.html](http://mathworld.wolfram.com/CosmologicalTheorem.html). +The non-[primordial](https://en.wikipedia.org/wiki/Primordial_nuclide) +[transuranic elements](https://en.wikipedia.org/wiki/Transuranium_element) are +the [isotopes](https://en.wikipedia.org/wiki/Isotope) of +[Neptunium](https://en.wikipedia.org/wiki/Neptunium) and +[Plutonium](https://en.wikipedia.org/wiki/Plutonium). Isotopes of a given +[element](https://en.wikipedia.org/wiki/Chemical_element) differ only in the +last digit. Four common elements could also be written as isotopes of these two +elements: `He=Np(2)`, `Li=Pu(2)`, `Ta=Np(3)`, `W=Pu(3)`. To get other isotopes, +just change the last digit to a number greater than 3. -The build file runs prog.c through the C preprocessor to -generate prog2.c which is edited with ed to correct spacing +The build file runs [jdalbec.c](jdalbec.c) through the C preprocessor to +generate `jdalbec2.c` which is edited with `ed(1)` (NOTE: this was +changed to `sed(1)` by the judges) to correct spacing problems caused by some preprocessors. (I know you dislike -Perl, but hopefully ed is more common on POSIX systems than -Perl.) The build file then compiles prog2.c and removes the -prog2.c file. +Perl, but hopefully `ed(1)` is more common on POSIX systems than +Perl.) The build file then compiles `jdalbec2.c]` and removes the +`jdalbec2.c` file. -I don't think I'm abusing the build file since I'm only using -147 characters including white space and the #! line and the -commented-out "-Wall -pedantic" options. The rules for the -16th IOCCC rules specifically allowed build files up to 521 +I don't think I'm abusing the [Makefile](Makefile) since I'm only using +147 characters including white space and the `#!` line and the +commented-out `-Wall -pedantic` options. The [rules for the +16th IOCCC](/2004/rules.txt) specifically allowed build files up to 521 characters long so my build file would have been well within those limits. (What typo?) -gcc -E -Wall -pedantic complains that trigraphs are present and that -"pasting ... does not yield a valid processing token". +`gcc -E -Wall -pedantic` complains that trigraphs are present and that +`"pasting ... does not yield a valid processing token"`. -gcc -ansi -Wall -pedantic complains about #line directives, +`gcc -ansi -Wall -pedantic` complains about `#line` directives, trigraphs, and expressions and statements that have no effect. The last complaint is false in all but one case. Removing the offending expressions causes some compilers to report @@ -86,7 +88,7 @@ refers to a variable or a type. Since buffer overflows are a common security problem these days I have stolen the idea of using a "safe" buffer API from -vsftpd. This means the program should never crash, right? +`vsftpd`. This means the program should never crash, right? The program was tested on: AMD K6/MMX 266MHz, Debian GNU/Linux testing "Sarge", gcc 3.3.2 @@ -98,78 +100,81 @@ Sun SPARC Ultra 10, Solaris 8, gcc 3.2 Compiling on Mac OS 8.6 requires some degree of manual intervention because Mac OS 8.6 doesn't have shell scripting -or even a normal command prompt. The CodeWarrior 11 compiler +or even a normal command prompt. The `CodeWarrior` 11 compiler is the reason I had to use trigraphs. I have to preprocess -prog.c without trigraphs, save the result as prog2.c, then -compile prog2.c with trigraphs to get the program to work. +`jdalbec.c` without trigraphs, save the result as `jdalbec2.c`, then +compile `jdalbec2.c` with trigraphs to get the program to work. I also have to add an include file and a function call to the program to get a pseudo command line so I can pass arguments. The compiler also requires function prototypes by default, which is why I have prototypes for all my functions. -Compiling on Mac OS X 10.1.5 requires changing ??= to \# on -line 3 because the compiler doesn't recognize ??= as a trigraph +Compiling on Mac OS X 10.1.5 requires changing `??=` to `#` on +line 3 because the compiler doesn't recognize `??=` as a trigraph (which I consider a compiler bug). The initial preprocessing step on Mac OS X 10.1.5 generates lots of errors in "smart mode" because the "smart" preprocessor expects a valid C program as input. The preprocessor then falls back to "basic -mode" and preprocesses prog.c successfully without warnings, -even when I give it the "-Wall -pedantic" options. It inserts +mode" and preprocesses `jdalbec.c` successfully without warnings, +even when I give it the `-Wall -pedantic` options. It inserts a lot of extra spaces into the preprocessed output which is -why I had to add the "ed" step to the build file so that my -macro #defines would work. The compile step gives the usual -messages with "-Wall -pedantic". The link step generates a -warning about a name conflict between my BC() and a BC() from +why I had to add the `ed` step to the build file so that my +macro `#defines` would work. The compile step gives the usual +messages with `-Wall -pedantic`. The link step generates a +warning about a name conflict between my `BC()` and a `BC()` from curses in the main system library. -BUGS, I mean FEATURES: -Arguments matching /[^2]22$/ cause the program to segfault +### BUGS FEATURES: + +Arguments matching `/[^2]22$/` cause the program to segfault after rapidly exhausting the available stack space. I could probably fix this by adding some special cases to the code, but [Blaine the Mono] it's quite a bit more exciting this way, -don't you think?[/Blaine] Since the trailing "22" will be +don't you think?[/Blaine] Since the trailing `22` will be its own atom anyway, you can just insert a space in front of -it if you run into this feature (e.g. "1 22" instead of "122"). +it if you run into this feature (e.g. `1 22` instead of `122`). -Note: you may want to be sure you have a limit on stack size -before trying this. I ran it on Debian GNU/Linux and discovered -that I did not have a limit on stack size. Fortunately the -OS killed the process after a while. This is consistent with -the output of 1996/schweikh3 which reports "malloc lied! -Killed by SIGKILL". +Note: you may want to be sure you have a limit on stack size before trying this. +I ran it on Debian GNU/Linux and discovered that I did not have a limit on stack +size. Fortunately the OS killed the process after a while. This is consistent +with the output of [1996/schweikh3](/1996/schweikh3/schweikh3.c) which reports +`malloc lied! Killed by SIGKILL`. -Arguments matching /(?:.){10,}/ will produce visually incorrect +Arguments matching `/(?:.){10,}/` will produce visually incorrect results (e.g., generation 1 starting from 1111111111 will -print as ": 1"), but there's nothing interesting about these +print as `: 1`), but there's nothing interesting about these arguments that can't be modeled using shorter runs of the same symbol. -Arguments matching /(?:.){257,}/ may produce mathematically +Arguments matching `/(?:.){257,}/` may produce mathematically incorrect results (e.g., generation 1 starting from a string -of 257 1's will be calculated as "11"); the remark from the +of 257 `1`s will be calculated as `11`); the remark from the previous paragraph applies here also. The program has exactly 2004 IOCCC countable bytes. It's tailor-made for this competition! Although there are no comments, the program still manages to -be self- documenting in an obscure fashion (periodic table of +be self-documenting in an obscure fashion (periodic table of the (non-primordial) elements, "OBFUSCATED C"). +### Obfuscation + The program is obfuscated: -By invoking cpp twice -By the use of #defines -By the use of typedefs -By the use of global constants -By the use of global functions that replace the standard ones (I -particularly like substituting At (Astatine, highly unstable) for abort.) -By overloading symbols (For example, B is a type, a structure, a structure -member, a macro parameter, and a variable.) -By standard tricks like writing '\0' as 1["3"] or 2["22"] -By using ternary operators to avoid "else" -By using the Sb function to create subbuffers from either end -By naming everything after chemical elements or pairs of elements -Because it says so in the source. ;) + +- By invoking `cpp` twice. +- By the use of `#define`s. +- By the use of `typedef`s. +- By the use of global constants. +- By the use of global functions that replace the standard ones (I particularly +like substituting `At` ([Astatine](https://en.wikipedia.org/wiki/Astatine), +highly unstable) for `abort()`.) By overloading symbols (For example, `B` is a +type, a structure, a structure member, a macro parameter, and a variable.). +- By standard tricks like writing `'\0'` as `1["3"]` or `2["22"]`. +- By using ternary operators to avoid `else`. +- By using the Sb function to create sub-buffers from either end. +- By naming everything after chemical elements or pairs of elements. +- Because it says so in the source. ;) ## Copyright and CC BY-SA 4.0 License: diff --git a/2004/kopczynski/Makefile b/2004/kopczynski/Makefile index 51af9451f..4f3266e2f 100644 --- a/2004/kopczynski/Makefile +++ b/2004/kopczynski/Makefile @@ -66,7 +66,7 @@ CINCLUDE= # Optimization # -OPT= -O3 +OPT= # Default flags for ANSI C compilation # diff --git a/2004/kopczynski/README.md b/2004/kopczynski/README.md index d1b6ed156..275e23990 100644 --- a/2004/kopczynski/README.md +++ b/2004/kopczynski/README.md @@ -1,12 +1,8 @@ # Best one-liner - Eryk Kopczynski - Faculty of Mathematics, Informatics and Mechanics - ul. Banacha 2 - 02-097 Warszawa - Poland - - http://www.mimuw.edu.pl/~erykk/ +Eryk Kopczynski +Poland + ## To build: @@ -20,6 +16,11 @@ make ./kopczynski < input_file ``` +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) reported that this +entry cannot be optimised by the compiler if it's to work. He also added the +file [kopczynski-a](kopczynski-a) to demonstrate what happens when art more like +a letter is fed to the program. Thank you Cody! + ## Try: ```sh @@ -31,6 +32,17 @@ make ./kopczynski < kopczynski-11 ``` +Also try: + +```sh +./kopczynski < kopczynski-a +``` + +What happens? + +What happens if you feed the program source to the program? Can you figure out +why? + ### Alternate code The judges modified the program to print its result. The original @@ -47,7 +59,7 @@ Then try: echo $? ``` -## Judges' remarks +## Judges' remarks: What is in a line? A lot when you obfuscate the way Eryk Kopczynski did it. This small one line program is an outstanding technical @@ -69,10 +81,10 @@ Here is a related puzzle: how to continue the sequence: 1, 0, 0, 0, 0, 0, 1, 0, 2, 1, ... -With certain arguments, you can alter the exit value. Can you figure +With certain arguments, you can alter the exit value / output. Can you figure out how and why? -## Author's remarks +## Author's remarks: The program proves it is not as hard to recognize numbers. The current one liner version should correctly recognize all numbers from 8 to 11. @@ -81,112 +93,108 @@ recognize negatives, zeros which have dots or slashes inside them, digits should be separated, and numbers should be "complete".) This program returns the number as its exit status. (In most shells, -you can see the exit status of the last command with 'echo $?' (or -just '$?').) +you can see the exit status of the last command with `echo $?` (or +just `$?`).) - [[NOTE: The judges altered the primary version to output a number.]] +**NOTE: The judges altered the primary version to output a number.** On the input, give numbers formed as a sequences of empty spaces and # signs (you can also use dots instead of spaces), ending with an empty line. (No number has an empty line in it.) The program should return the number from 8 to 11 that it thinks it is. -* The line is 131 bytes long (in 1986 165 bytes was OK, and the size +* The line is 131 bytes long (in 1986, 165 bytes was OK, and the size limit has grown from 1986...). * I have decided that it is better for this program to return the number, not to print it, but if you think otherwise, the change would - cost 6 chars (plus a warning). Change 'return *' to 'printf("%d",*)'. - ('$?' is shorter) + cost 6 chars (plus a warning). Change `return *` to `printf("%d",*)`. + (`$?` is shorter) -* I achieved some additional tightness by '-Dif=while', saved 9 chars - of source for cost of 11 chars of build file. If I used '-DB=while', - I would save 12 for 10, but I think the current version is slightly - more obfuscated. +* I achieved some additional tightness by `-Dif=while` which saved 9 chars of +source for the cost of 11 chars of the [Makefile](Makefile). If I used +`-DB=while`, I would save 12 for 10, but I think the current version is slightly +more obfuscated. -* A remark on portability: +### Portability - It only requires two's compliment arithmetics, as far as I - know. The maximum length of an input line is N-9, where - N is the size of int in bits (you can try to compile with - an option '-Dint=long long' for longer lines). +It only requires two's complement arithmetics, as far as I know. The maximum +length of an input line is `N-9`, where `N` is the size of `int` in bits +(you can try to compile with an option `'-Dint=long long'` for longer +lines). - -- Algorithm & Obfuscation -- +### Algorithm & Obfuscation -1. This program works by calculating the Euler characteristics of input, - plus 9. It is the number of digits (i.e. separated #-regions) minus the - number of holes in them. It turns out that this algorithm works - correctly for all numbers from 8 to 11. +1. This program works by calculating the [Euler +characteristics](https://en.wikipedia.org/wiki/Euler_characteristic) of input, +plus 9. It is the number of digits (i.e. separated #-regions) minus the number +of holes in them. It turns out that this algorithm works correctly for all +numbers from 8 to 11. -2. We know that Euler characteristics is the number of "vertexes" +2. We know that [Euler +characteristics](https://en.wikipedia.org/wiki/Euler_characteristic) is the number of "vertexes" - # + # minus the number of "edges" - ## # #. .# - # .# #. ('.' must be empty) + ## # #. .# + # .# #. ('.' must be empty) plus the number of "faces" - ## - ## + ## + ## 3. If we fill all these patterns to 2x2 squares, - #? ## #? #. .# ## - ?? ?? #? .# #. ## - +1 -1 -1 -1 -1 +1 + #? ## #? #. .# ## + ?? ?? #? .# #. ## + +1 -1 -1 -1 -1 +1 - substitute all possible "values" of '?' and sum up, we get that it is + substitute all possible "values" of `?` and sum them up, we get that it is enough to calculate: - #. .# ## - .. #. #. - +1 -1 -1 + #. .# ## + .. #. #. + +1 -1 -1 Note now it is simple and obfuscated enough to be used as a "magic trick". 4. I make a 16-character array; when indexed by 4-bit value which represents the 2x2 squares, it will return a number to add/subtract - {-1,0,+1} + `{-1,0,+1}` -5. We convert lines of input to bitmaps (N-bit integers). Additionally, - it is heavily obfuscated by using negative numbers (two's compliment). - For example, it turns out that 6 in "z=6" in the only 1-digit number - which works here (and it's not only because we have "z>5" in the - following while). The conversion routine also sets n=8 in an obfuscated - and concise way. +5. We convert lines of input to bitmaps (`N-bit` integers). Additionally, it is +heavily obfuscated by using negative numbers (two's complement). For example, +it turns out that `6` in `z=6` is the only 1-digit number which works here (and +it's not only because we have `z>5` in the following `while`). The conversion +routine also sets `n=8` in an obfuscated and concise way. -5. Since we always return the number from 8 to 11, we can calculate - modulo 4. Instead of 16 {-1,0,+1} values, we use a 15-character string - which agrees modulo 4 to the array in (4). (NUL fits very well as the - 16th character, so we use 15-character string.) +6. Since we always return the number from 8 to 11, we can calculate modulo 4. +Instead of `16 {-1,0,+1}` values, we use a 15-character string which agrees +modulo 4 to the array in (`4`). (`NUL` fits very well as the 16th character, so +we use 15-character string.) -6. Since the rule found in (3) did not produce any funny messages, I - changed it until it did. (The # character to find vertexes is in the - top right corner, not the top left one.) The following messages will - also work instead of "has dirtiest IF": +7. Since the rule found in (3) did not produce any funny messages, I changed it until it did. (The `#` character to find vertexes is in the top right corner, not the top left one.) The following messages will also work instead of `has dirtiest IF`: - HighlandYachter - TestDirtiestTen - has lintiest IF - TighterLaughter - HustlerDaughter - TighterDemoThen + HighlandYachter + TestDirtiestTen + has lintiest IF + TighterLaughter + HustlerDaughter + TighterDemoThen They can be mixed, of course! -7. [[NOTE: Item 7 was removed by the judges so as to not spoil the - challenge of figuring how arguments can be used to alter - the exit value.]] +8. NOTE: item 8 was removed by the judges so as to not spoil the challenge of +figuring how arguments can be used to alter the exit value. -8. The variable names are confusing. +9. The variable names are confusing. -9. Finally, the program tries to be as concise as possible. Some - obfuscation comes from this. For additional obfuscation and - conciseness, 'if' means 'while'. +10. Finally, the program tries to be as concise as possible. Some obfuscation +comes from this. For additional obfuscation and conciseness, `if` means `while`. ## Copyright and CC BY-SA 4.0 License: diff --git a/2004/kopczynski/kopczynski-a b/2004/kopczynski/kopczynski-a new file mode 100644 index 000000000..40d5db0ed --- /dev/null +++ b/2004/kopczynski/kopczynski-a @@ -0,0 +1,8 @@ + #### + ###### + ## ## + ### ### + ########## + ## ## + ## ## + diff --git a/2004/newbern/README.md b/2004/newbern/README.md index 33939768b..decab0d3e 100644 --- a/2004/newbern/README.md +++ b/2004/newbern/README.md @@ -1,8 +1,7 @@ # Best Font Engine - Jeff Newbern - 28 Jeanette Ave. #1 - Belmont, MA 02478 +Jeff Newbern +US ## To build: @@ -11,8 +10,8 @@ make ``` [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) and Landon individually -fixed this to work with clang. Cody turned the second arg to main, which clang -requires to be a `char **`, to be not the same name as a function defined +fixed this to work with clang. Cody then turned the second arg to main, which +clang requires to be a `char **`, to be not the same name as a function defined earlier in the code and to use that variable which `main()` used. Thank you Cody for your assistance! @@ -41,26 +40,23 @@ This is a configurable banner-like program. ### Examples: -- To convert a character glyph into a data file +- To convert a character glyph into a data file: -```sh -./newbern char < some_nicely_shaped_text >> data_file -``` + ./newbern char < some_nicely_shaped_text >> data_file -- To print a string using glyphs from a data file -```sh -./newbern data_file a_string -``` +- To print a string using glyphs from a data file: -### Extra functionality: + ./newbern data_file a_string + +### Extra functionality The program can also act as a Morse encoder, unarguably. It also has double-super-secret encryption capabilities. Decryption is left as an exercise for the reader. -### Portability: +### Portability The program assumes an ASCII operating environment. diff --git a/2004/omoikane/README.md b/2004/omoikane/README.md index c0059be8e..805276e85 100644 --- a/2004/omoikane/README.md +++ b/2004/omoikane/README.md @@ -1,11 +1,8 @@ # Best Utility - Don Yang - 259 E. Bellbrook St. - Covina, CA 91722 - USA - - http://uguu.org/ +Don Yang +US + ## To build: @@ -34,18 +31,18 @@ is modified to have the desired checksum! This does, we suppose, solve the problem that inserting a checksum would change the file's checksum; if you have to change it, you might as well change it! -This program was submitted under the name "Rinia", so the Author's +This program was submitted under the name `Rinia`, so the Author's Comments refer to it as such. ## Author's remarks: -Rinia (1/14/04) +**Rinia (1/14/04)** -Rinia is a tool for embedding CRCs in text files. No need to assign +`Rinia` is a tool for embedding CRCs in text files. No need to assign strange file names or package .SFVs with your files! Rinia will -insert a human-readable checksum string in the text itself! ^_^ +insert a human-readable checksum string in the text itself! `^_^` -0. Usage ` +### Usage ` ```sh rinia @@ -54,20 +51,20 @@ rinia All three arguments may reference the same file. All files is assumed to be of ASCII character set. -1. Input % +### Input % Any file larger than 8 bytes is valid. Upper limit on file size is limited by memory. -If input file can't be loaded for any reason, Rinia will say "bad +If input file can't be loaded for any reason, `Rinia` will say "bad input" and exit immediately. -2. Layout _ +### Layout _ -The layout file contains a map of where Rinia can patch. The -content consists of marker characters (where Rinia is allowed to +The layout file contains a map of where `Rinia` can patch. The +content consists of marker characters (where `Rinia` is allowed to change in the original text) and other characters (where the -original text will stay as is). Rinia will select the marker +original text will stay as is). `Rinia` will select the marker character using these heuristics: 1. Ignore all space/control/extended characters. @@ -76,95 +73,103 @@ character using these heuristics: frequency. One way to create the layout file is to make a copy of the original -file, replace where you want Rinia to match with a rare character, +file, replace where you want `Rinia` to match with a rare character, then replace the remaining ones with space. Often it's possible to write the original file in such a way that it can be used as a layout. Example file/layout: +``` file: layout: crc = ######## ... . XXXXXXXX patch = ###### ..... . XXXXXX other text here ..... .... .... +``` -And Rinia may generate a file similar to this: +And `Rinia` may generate a file similar to this: +``` crc = 1bad73cf patch = #FR-QQ other text here +``` Note that the original file by itself is a valid layout file, since -Rinia will recognize that only # marks enough space to hold the +`Rinia` will recognize that only `#` marks enough space to hold the checksum, and has the lowest frequency. -If layout file can't be used for any reason, Rinia will say "bad +If layout file can't be used for any reason, `Rinia` will say "bad layout" and exit immediately. -3. Output m +### Output m -If Rinia finds a usuable checksum, she will say "OK." and write to +If `Rinia` finds a usable checksum, she will say "OK." and write to the specified output file. Otherwise the exit message is "fail" and nothing is written. Chances of success and how long it takes to run to completion is -completely dominated by the layout file design. In general, Rinia +completely dominated by the layout file design. In general, `Rinia` runs faster if the checksum is placed before the other marker characters rather than after, e.g.: +``` a: X X XXX b: XXXXXXXX c: XXXXXXXX XXXXXXXX X X XXX XXXXX -"a" usually takes the longest time, while "c" usually is the +``` + +`a` usually takes the longest time, while `c` usually is the fastest. That said, each run is randomized with respect to system time, so -it's not always certain whether Rinia will succeed in a short time -or not. In general, 5 marker characters is sufficient, and takes +it's not always certain whether `Rinia` will succeed in a short time +or not. In general, 5 marker characters are sufficient, and takes a few minutes. -For reference, rinia.c was produced on a 1.7GHz machine (the +For reference, `rinia.c` was produced on a 1.7GHz machine (the checksum is at line 17). Out of 25 runs, the shortest was 2 seconds while the longest took 5 minutes. Average was about a -minute. Checksum for this file (b7a81524) took about 4 minutes. +minute. Checksum for this file (`b7a81524`) took about 4 minutes. -4. Algorithm 3 +### Algorithm Inserting a checksum in the file you are computing the checksum of isn't quite trivial, since changing the file content would change the final checksum value. -To insert the checksum, Rinia first assumes a random final +To insert the checksum, `Rinia` first assumes a random final checksum, insert that string, then modify other parts to compensate for the change in content. The compensation bytes are very easy to compute for binary files with enough consecutive scratch areas, but for text files with -non-consecutive areas and limited degrees of freedom, Rinia has to +non-consecutive areas and limited degrees of freedom, `Rinia` has to try out all character combinations. This is done in a hierarchical fashion, computing only smallest partial checksum after each change. For computers few years ago, this is probably still too slow to be -acceptible... but at the speed the IOCCC judges run the contest -these days, I am sure you have enough patience for it ^_^; +acceptable... but at the speed the IOCCC judges run the contest +these days, I am sure you have enough patience for it `_^` -5. Source code = +### Source code -rinia.c should compile anywhere (but with a few warnings). I don't -have a big-endian machine to test but Rinia should work there as +`rinia.c` should compile anywhere (but with a few warnings). I don't +have a big-endian machine to test but `Rinia` should work there as well. ASCII character set required though. -Code is formatted to the shape of "Rinia" from the anime/game +Code is formatted to the shape of "`Rinia`" from the anime/game "Moekko Company". Of course at 90x50 it's hard to recognize anything -^_^; +`^_^` -Rinia is the slow but hardworking android. On some jobs she does +`Rinia` is the slow but hardworking android. On some jobs she does very well, on others she would spend lots of time and effort but still fail... -(text above is also included as an info file, so that the checksum -would match) +NOTE: the text above is also included as an info file but in original format, so +that the checksum would match. The above was formatted in markdown for GitHub +and the IOCCC website. ## Copyright and CC BY-SA 4.0 License: diff --git a/2004/schnitzi/README.md b/2004/schnitzi/README.md index e50c86aa4..27f08335c 100644 --- a/2004/schnitzi/README.md +++ b/2004/schnitzi/README.md @@ -1,9 +1,6 @@ # Best Non-Use of Curses Mark Schnitzius -Eclipse Group -94 Richardson St -Albert Park, VIC 3206 Australia @@ -22,8 +19,8 @@ make ## Try: ```sh -./schnitzi /dev/null| vi +./schnitzi /dev/null| vi ``` For others, create an output file and use your system @@ -34,6 +31,18 @@ pasteboard/selection/cut buffer to "input" the output into vi: ./schnitzi schnitzi.out1 ``` +NOTE: if you're one of those who don't know how to exit `vi` :-) don't worry as +it will exit for you. + +NOTE: this entry will make vi(m) swap files in the current working directory. +You might wish to clean them up. We could say how but lest there is another file +that matches the glob we won't. In any event vi swap files start with a dot +followed by the file name followed by another dot followed by `s` and two more +letters like. If no file is opened it will not have the file name but just be +e.g. `.swp`. When a second letter has no remaining availabilities it goes to +another one e.g. `u`. + + ## Judges' remarks: This exemplifies the meaning of Visual Editor, but we don't think @@ -43,7 +52,7 @@ performance of the latest hardware! ## Author's remarks: If you've ever pasted a large chunk of text into an editor (such as -'vi') without first putting it into insert mode, or turning off +`vi`) without first putting it into insert mode, or turning off the auto-indent, you know the dismay of watching your screen fill up with misaligned junk. @@ -70,10 +79,10 @@ which appear later in the input file will be drawn in front of sprites which appear earlier. The output, to stdout, is a string which, when pasted into vi, will -perform the animation defined in the input. [The vi editor is a +perform the animation defined in the input. (The vi editor is a common (and ancient) editor that should be available on most Unix, Linux, Solaris, and Mac OS X machines; you can get it on Windows -by installing Cygwin, which is how I do it.] +by installing Cygwin, which is how I do it.) ### THE INPUT @@ -83,17 +92,17 @@ description of the input file format. The first line is specified thusly: +``` [duration] [timefactor] +``` -The first parameter, duration, defines how long the animation will -run. The second, timefactor, is used as sort of a fudge factor -for machines that run too fast to see the animation. A timefactor -of 0 means, "run the animation as fast as you can". On a pretty -fast machine, I've had to set it as high as 2000 to get the -animation to slow down sufficiently. Note that the higher the -timefactor, the longer the output string that you'll have to copy- -and-paste, as extra characters are necessary to "waste time" between -frames. +The first parameter, duration, defines how long the animation will run. The +second, `timefactor`, is used as sort of a fudge factor for machines that run +too fast to see the animation. A `timefactor` of 0 means, "run the animation as +fast as you can". On a pretty fast machine, I've had to set it as high as 2000 +to get the animation to slow down sufficiently. Note that the higher the +`timefactor`, the longer the output string that you'll have to copy- and-paste, +as extra characters are necessary to "waste time" between frames. Following the first line parameters, you may have up to nine different sprites, each up 50 by 50 in size, and with up to four @@ -101,22 +110,32 @@ different 'views' of that object, which are cycled through with each successive frame. Each sprite begins with a line of parameters of the following form: +``` [start] [end] [x] [y] [dx] [dy] [cols] [rows] [viewcount] +``` where: -'start' is the time at which this sprite first appears -'end' is the time at which it disappears -'x' is the horizontal position at which it starts -'y' is the vertical position -'dx' is the amount that the x position changes per frame -'dy' is the amount that the y position changes per frame -'cols' is the number of columns in each view -'rows' is the number of rows in each view -'viewcount' is the number of views to cycle through +- `start` is the time at which this sprite first appears. -Each such parameter line will be followed by 'viewcount' -view frames, each with 'rows' rows and 'cols' columns. +- `end` is the time at which it disappears. + +- `x` is the horizontal position at which it starts. + +- `y` is the vertical position. + +- `dx` is the amount that the `x` position changes per frame. + +- `dy` is the amount that the `y` position changes per frame. + +- `cols` is the number of columns in each view. + +- `rows` is the number of rows in each view. + +- `viewcount` is the number of views to cycle through. + +Each such parameter line will be followed by `viewcount` +view frames, each with `rows` rows and `cols` columns. Input is terminated by end of file. Duh. diff --git a/2004/sds/.gitignore b/2004/sds/.gitignore index 494c133dd..b1057c76f 100644 --- a/2004/sds/.gitignore +++ b/2004/sds/.gitignore @@ -1 +1,8 @@ sds +encoder +encoder.c +message +sds2_msg +sds2_msg.c +sds_msg +sds_msg.c diff --git a/2004/sds/Makefile b/2004/sds/Makefile index b7c9c4a86..0b74ecbce 100644 --- a/2004/sds/Makefile +++ b/2004/sds/Makefile @@ -61,7 +61,7 @@ CDEFINE= # Include files that are needed to compile # -CINCLUDE= +CINCLUDE= -include stdlib.h # Optimization # diff --git a/2004/sds/README.md b/2004/sds/README.md index 4483399ca..12c91e8b7 100644 --- a/2004/sds/README.md +++ b/2004/sds/README.md @@ -1,11 +1,8 @@ # Best Abuse of Indentation - Stephen Sykes - Laivalahdenportti 2 - 00810 Helsinki - Finland - - http://www.stephensykes.com +Stephen Sykes +Finland + ## To build: @@ -24,9 +21,28 @@ make ```sh ./sds < sds.c > encoder.c make encoder -./encoder sds.hint sds_msg.c +./encoder README.md sds_msg.c +make sds_msg +./sds_msg < sds.c > sds2_msg.c +diff sds2_msg.c encoder.c ``` +Also try: + +```sh +echo 'Hello, World!' > message +./encoder message < README.md > remarks.md +diff remarks.md README.md # notice how similar they are + +# and then observe: +./sds < remarks.md +``` + +### INABIAF - it's not a bug it's a feature! :-) + +The generated code will very likely crash or do something else if not given a +proper command line. This is not a bug but a feature. + ## Judges' remarks: Why not use the program to hide another program in the program? It @@ -97,14 +113,16 @@ changed inside strings where it should be left alone. Plain text files are good candidates for hiding information in, but the added spacing may render the text somewhat difficult to read. +### Obfuscation + This program is obfuscated in a number of ways: -* The code is all but impossible to read due to the spacing -* The algorithm is well hidden in the code due to copious red-herrings -* The long expressions cause indentation tools to give poor results -* And good old fashioned ternery operators are the icing on the cake +* The code is all but impossible to read due to the spacing. +* The algorithm is well hidden in the code due to copious red-herrings. +* The long expressions cause indentation tools to give poor results. +* And good old fashioned ternary operators are the icing on the cake. -Compiling the program +### Compiling the program The program (and the encoder program) should compile on any reasonable compiler. In particular, they are known to compile under diff --git a/2004/vik1/README.md b/2004/vik1/README.md index 2c1d34f19..995b97ef6 100644 --- a/2004/vik1/README.md +++ b/2004/vik1/README.md @@ -1,11 +1,10 @@ # Best X11 Game - Daniel Vik - 926 Genter Street - La Jolla, Ca 92037 - USA - - http://www.vik.cc/ +Daniel Vik +US + + + ## To build: @@ -28,11 +27,16 @@ make ./vik1 ad3 ``` +Can you figure out how to cheat? + ## Judges' remarks: -Danial Vik has presented a tour de force feature rich X11-based -racing game that fit within the contest size limits. Take a -glace at the feature list he provided below. Amazing! +Daniel Vik has presented a tour de force feature rich X11-based +racing game that fit within the contest size limits. Take a +glance at the feature list he provided below. Amazing! + +The author posted a video of this on YouTube: +. Happy touring on the road and in the code! @@ -54,11 +58,11 @@ This program is a complete car race game with a lot of nice features: * Slippery road when driving in the winter. -* When driving off the road, the car slows down to a halt +* When driving off the road, the car slows down to a halt. * Three different race tracks that takes about one minute to complete. -* Speed meter. +* Speedometer. * Computer driven opponent cars. @@ -71,69 +75,74 @@ This program is a complete car race game with a lot of nice features: ### Build and Run Compile the source code and link x libraries if necessary. -The program takes three options which have to be typed in a specific +The program takes three options which have to be typed in a specific order as described below. - Usage: vik1 ['a']['d'][#] +```sh +Usage: ./vik1 ['a']['d'][#] - a - Advanced racing in a winter landscape - d - Racing in at night in the dark - # - Race track selection 1-3 are valid numbers +a - Advanced racing in a winter landscape +d - Racing in at night in the dark +# - Race track selection 1-3 are valid numbers +``` Here are a few examples: +``` Command line: Description: + $ ./vik1 Run track 1 at daytime in the summer $ ./vik1 a Run track 1 at daytime in the winter $ ./vik1 d Run track 1 at night in the summer $ ./vik1 3 Run track 3 at daytime in the summer $ ./vik1 d3 Run track 3 at night in the summer $ ./vik1 ad2 Run track 2 at night in the winter +``` -Note that the order in which the argument characters are entered is -important. It is for example not possible to type ./vik1 da. (Well it is +Note that the order in which the argument characters are entered is +important. It is for example not possible to type `./vik1 da`. (Well it is possible, but the result will not be as expected.) -The space key accelerates the car. Releasing the space key slowly -reduces the speed. The left and right arrow keys are used to steer the +The space key accelerates the car. Releasing the space key slowly +reduces the speed. The left and right arrow keys are used to steer the car. ### Obfuscation -The main obfuscation is the fact that the program is extremely compact. -There are a few things I didn't want to do, e.g. define #define to a +The main obfuscation is the fact that the program is extremely compact. +There are a few things I didn't want to do, e.g. define `#define` to a single letter to save some space, or to remove casts to save some space. -The program uses a lot of variables. In fact, all letters a-z are used +The program uses a lot of variables. In fact, all letters a-z are used and most letters A-Z. -The constants are chosen very carefully and thy have multiple purposes, +The constants are chosen very carefully and they have multiple purposes, e.g. a constant can be both the length of the track and a color. -Most of the code is kept inside five for loops without body. Each for -loop does many things. One for loop draws all cars by restarting a +Most of the code is kept inside five for loops each without a body. Each for +loop does many things. One for loop draws all cars by restarting a couple of times. Another draws the road, mountains, and the sun. -Main is called recursively. The return value and output depends on the -arguments. main can return the current time, draw lines and of course be -the entrypoint of the application. +`main()` is called recursively. The return value and output depends on the +arguments. `main()` can return the current time, draw lines and of course be +the entry point of the application. -The program frequently uses the ? operator mainly to save space but it +The program frequently uses the `?:` operator mainly to save space but it makes the program more obscure. ### Compiler warnings -There are no compiler warnings when compiling with -ansi but there are -quite many warnings from lclint. Mainly because the program is very +There are no compiler warnings when compiling with -ansi but there are +quite many warnings from lclint. Mainly because the program is very optimized for code size. ### Limitations The program only compiles and runs on X based systems. -The program requires a display with 24 bit color depth. It also assumes -that the byte order of the colors are as on my Linux PC. That is, The -colors are represented by a 32 bit value where the bytes (from high to +The program requires a display with 24 bit color depth. It also assumes +that the byte order of the colors are as on my Linux PC. That is, The +colors are represented by a 32 bit value where the bytes (from high to low) are { 0, RED, GREEN, BLUE }. ## Copyright and CC BY-SA 4.0 License: diff --git a/2004/vik2/README.md b/2004/vik2/README.md index 259bc83e9..4c0d9a0cb 100644 --- a/2004/vik2/README.md +++ b/2004/vik2/README.md @@ -1,11 +1,9 @@ # Best Abuse of CPP - Daniel Vik - 926 Genter Street - La Jolla, Ca 92037 - USA - - http://www.vik.cc/ +Daniel Vik +US + + ## To build: @@ -27,174 +25,194 @@ echo "Do or do not. There is no try." ## Judges' remarks: -The fun thing about CPP abuses is that, in most cases, running the -preprocessor on them doesn't help you decipher the obfuscated code. -That's assuming your preprocessor can take it at all. +The fun thing about [CPP](https://en.wikipedia.org/wiki/C_preprocessor) abuses +is that, in most cases, running the +[preprocessor](https://en.wikipedia.org/wiki/C_preprocessor) on them doesn't +help you decipher the obfuscated code. That's assuming your preprocessor can +take it at all. ## Author's remarks: ### Introduction -It's been a while since the last pre-processor killer won the ioccc. -I thought it was time to relive hour long compile times so I made a -program that does (almost) all computation in the pre-processor. The -program even causes gcc (and other pre-processors) to crash when -configured to do maximum number of computations. -The default configuration of the makefile is set to make the program -compile in a not too long time. +It's been a while since the last +[pre-processor](https://en.wikipedia.org/wiki/C_preprocessor) killer won the +IOCCC. I thought it was time to relive hour long compile times so I made a +program that does (almost) all computation in the pre-processor. The program +even causes `gcc` (and other pre-processors) to crash when configured to do +maximum number of computations. The default configuration of the +[Makefile](Makefile) is set to make the program compile in a not too long time. -I've got cpp to crash in a couple of diffenent ways. Most common is to -get a segmentation fault, but a couple of times it just got stuck in +I've got `cpp` to crash in a couple of different ways. Most common is to +get a segmentation fault, but a couple of times it just got stuck in some infinite loop. -I actually had to write my own pre-processor to verify that the program -was doing the right thing... +I actually had to write my own +[pre-processor](https://en.wikipedia.org/wiki/C_preprocessor) to verify that the +program was doing the right thing... -Since it takes a very long time to compile the program, there is a -symbol that can be defined to shorten the compile time and avoid +Since it takes a very long time to compile the program, there is a +symbol that can be defined to shorten the compile time and avoid compiler errors. ### Features -The program implements an 11-bit ALU in the pre-processor. The ALU has -two registers, X and Y, for calculations and one status register SR. -Each bit in the registers are represented by one symbol that are either -defined or undefined. +The program implements an 11-bit +[ALU](https://en.wikipedia.org/wiki/Arithmetic_logic_unit) in the +[pre-processor](https://en.wikipedia.org/wiki/C_preprocessor). The ALU has two +[registers](https://en.wikipedia.org/wiki/Processor_register), `X` and `Y`, for +calculations and one status register `SR`. Each bit in the registers are +represented by one symbol that are either defined or undefined. - The ALU has six instructions: +The ALU has six instructions: - CLR_X - Clear register X +- `CLR_X` - Clear [register](https://en.wikipedia.org/wiki/Processor_register) `X`. - CLR_Y - Clear register Y +- `CLR_Y` - Clear [register](https://en.wikipedia.org/wiki/Processor_register) `Y`. - ADD - Calculates X + Y and stores the result in X. If the result - is larger than 11 bits, the CARRY bit in SR is set otherwise - the CARRY bit is cleared. +- `ADD` - Calculates `X` + `Y` and stores the result in `X`. If the result + is larger than 11 bits, the [CARRY + bit](https://en.wikipedia.org/wiki/Carry_flag) in `SR` is set otherwise + the `CARRY` bit is cleared. - SUB - Calculates X - Y and stores the result in X. If Y was larger - than X, the CARRY bit in SR is set otherwise the CARRY bit - is cleared. +- `SUB` - Calculates `X` - `Y` and stores the result in `X`. If `Y` was larger + than `X`, the [CARRY bit](https://en.wikipedia.org/wiki/Carry_flag) + in `SR` is set otherwise the `CARRY` bit is cleared. - TST - If X == Y the EQ bit in SR is set, otherwise the EQ bit is - cleared. If X < Y the LT bit in SR is set, othervise the LT +- `TST` - If `X` == `Y` the `EQ` bit in `SR` is set, otherwise the `EQ` bit is + cleared. If `X` < `Y` the `LT` bit in `SR` is set, otherwise the `LT` bit is cleared. - INC2 - Calculates X + 2 and stores the result in X. The CARRY bit - is handled as in the ADD instruction. +- `INC2` - Calculates `X` + 2 and stores the result in `X`. The [CARRY + bit](https://en.wikipedia.org/wiki/Carry_flag) is handled as in the + `ADD` instruction. -Internally the ALU implements a one bit adder with a carry in and carry -out. This adder is the core of the ALU. The ADD instruction uses the one -bit adder to create the 11-bit adder. The SUB instruction is implemented -by adding ~Y to X and then add 1. Finally the TST instruction calculates -X-Y and checks the result and the CARRY bit in the SR register to set -the EQ and LT bits. +Internally the [ALU](https://en.wikipedia.org/wiki/Arithmetic_logic_unit) +implements a one bit adder with a carry in and carry out. This adder is the core +of the ALU. The `ADD` instruction uses the one bit adder to create the 11-bit +adder. The SUB instruction is implemented by adding `~Y` to `X` and then add 1. +Finally the `TST` instruction calculates `X-Y` and checks the result and the +[CARRY bit](https://en.wikipedia.org/wiki/Carry_flag) in the `SR` +[register](https://en.wikipedia.org/wiki/Processor_register) to set the `EQ` and +`LT` bits. -All calculations are made using only the #ifdef, #infdef, #else, #endif, -#define and #undef. I never assign a value to a defined symbol. The -logic is done by assuming that a defined symbol is 1 and an undefined +All calculations are made using only `#ifdef`, `#ifndef`, `#else`, `#endif`, +`#define` and `#undef`. I never assign a value to a defined symbol. The +logic is done by assuming that a defined symbol is 1 and an undefined symbol is 0. (I guess this means that I have unlimited memory as long as I only store zeroes (!)). -The application that uses the pre-processor ALU is a prime number -generator. The application uses the same pre-processor directives. -Needed variables are stored in memory represended by one defined or -undefined symbol per bit. When doing arithmetics, the variables are -loaded into the X and Y registers by defining / undefining the X and Y -register bits. Then the calcualtion is made and the result is moved back -to the memory. +The application that uses the +[pre-processor](https://en.wikipedia.org/wiki/C_preprocessor) +[ALU](https://en.wikipedia.org/wiki/Arithmetic_logic_unit) is a [prime +number](https://en.wikipedia.org/wiki/Prime_number) +generator. The application uses the same pre-processor directives. +Needed variables are stored in memory represented by one defined or +undefined symbol per bit. When doing arithmetics, the variables are +loaded into the `X` and `Y` registers by defining / undefining the `X` and `Y` +[register](https://en.wikipedia.org/wiki/Processor_register) bits. Then the +calculation is made and the result is moved back to the memory. -The choice of application may be a bit unfortunate since we've already -seen a winning entry calculating prime nubmers in the pre-processor. -There is a big difference though. The 1988 applin entry uses pre- -processor arithmethic (in a very nice way though). This program only -defines and undefines symbols in a well defined ;) way and doesn't do +The choice of application may be a bit unfortunate since we've already +seen a winning entry calculating [prime +numbers](https://en.wikipedia.org/wiki/Prime_number) in the +[pre-processor](https://en.wikipedia.org/wiki/C_preprocessor). +There is a big difference though. The 1988 applin entry uses pre- +processor arithmetic (in a very nice way though). This program only +defines and undefines symbols in a well defined ;) way and doesn't do any pre-processor arithmetics. -The reason why I choosed to do a prime number application is that the -algorithm can be written to do a lot of calculations without a lot of -nesting (gnu cpp allows only 200 nested includes). +The reason why I chose to do a [prime +number](https://en.wikipedia.org/wiki/Prime_number) application is that the +algorithm can be written to do a lot of calculations without a lot of nesting +(`gnu cpp` allows only 200 nested includes). ### Build and Run -First, do a first pre processing of the initial definitions. The FNAME -symbol must be defined to the name of the output file. If you want to -speed up the compilation, define the STOP symbol to anything from _3 to -_10. (The default value is _10 which will make the compilation take some -time.) Prime numbers up to 2^STOP will be calculated. +First, do a first pre-processing of the initial definitions. The FNAME +symbol must be defined to the name of the output file. If you want to +speed up the compilation, define the `STOP` symbol to anything from `_3` to +`_10`. (The default value is `_10` which will make the compilation take some +time.) Prime numbers up to `2^STOP` will be calculated. ```sh cpp '-DSTOP=_5' '-DFNAME="tmp1.c"' prog.c tmp1.c ``` -Then use cpp or any other pre-processor to do the actual work. This will -take some time.... +Then use `cpp` or any other +[pre-processor](https://en.wikipedia.org/wiki/C_preprocessor) to do the actual +work. This will take some time.... ```sh cpp tmp1.c > tmp2.c ``` -Finally compile the pre processed file +Finally compile the pre-processed file ```sh cc -O tmp2.c -o prog ``` -Then run the program to reveil all prime numbers up to 32 (if you used -STOP=_5 as above): +Then run the program to reveal all prime numbers up to 32 (if you used +`STOP=_5` as above): ```sh -./prog +./vik2 ``` ### Verification -I wasn't able to compile the full program which calculates prime numbers -up to 1024 using gnu cpp (or any other pre-processor) so I had to write -my own. Knowing how the program works it was quite easy to reduce the -compilation time from several hours to about one second. I also added -some statistics to my home made pre-processor and I found that -calculating prime numbers up to 1024 makes the program include itself -over 6.8 million times (see the statistics table below). +I wasn't able to compile the full program which calculates [prime +numbers](https://en.wikipedia.org/wiki/Prime_number) up to 1024 using `gnu cpp` +(or any other [pre-processor](https://en.wikipedia.org/wiki/C_preprocessor)) so +I had to write my own. Knowing how the program works it was quite easy to reduce +the compilation time from several hours to about one second. I also added some +statistics to my home made pre-processor and I found that calculating prime +numbers up to 1024 makes the program include itself over 6.8 million times (see +the statistics table below). ### Obfuscation -Well, since 98.5% of the program is preprocessor directives, the main -obfuscation is the use of preprocessor directives. +Well, since 98.5% of the program is +[preprocessor](https://en.wikipedia.org/wiki/C_preprocessor) directives, the +main obfuscation is the use of preprocessor directives. -Doing arithmetics without acutally using any arithmetic operations makes +Doing arithmetics without actually using any arithmetic operations makes the program quite hard to follow. -In order to actually do the calculations, the program includes itself a +In order to actually do the calculations, the program includes itself a lot. The symbol names are made as short as possible to meet the space limits. -This of course adds to the obfuscation (even though the program is +This of course adds to the obfuscation (even though the program is quite obfuscated with longer, readable macro names. -Finally, I made the 1.5% c code a bit harder to read by breaking all +Finally, I made the 1.5% C code a bit harder to read by breaking all lines after three characters. The program has 1029 lines which makes it the longest entry (so far). -Even though the pre-processed and indented output is easier to read, it +Even though the pre-processed and indented output is easier to read, it is quite hard to find the code in it. The size of the pre-processed file -is several Mb when using gnu cpp. +is several Mb when using `gnu cpp`. ### Limitations In order to fit the program within the space limits, I had to define the -#define, #endif, and some other directives as single character symbols. -This does not compile on all pre-processors but using gnu cpp as a first -compilation step solves this. +`#define`, `#endif`, and some other directives as single character symbols. +This does not compile on all +[pre-processors](https://en.wikipedia.org/wiki/C_preprocessor) but using `gnu +cpp` as a first compilation step solves this. ### Statistics -The table below contains some interesting statistics about the -compilation of the program. The intermediate file size is the size of -the output file of the cpp pre-processor. The time taken to pre process -the program were measured using gnu cpp on my 2.0MHz P4 with 512Mb ram -and a lot of disk. +The table below contains some interesting statistics about the compilation of +the program. The intermediate file size is the size of the output file of the +cpp [pre-processor](https://en.wikipedia.org/wiki/C_preprocessor). The time +taken to pre-process the program were measured using gnu cpp on my 2.0MHz P4 +with 512Mb ram and a lot of disk. +``` Generated Recursive Max nest Intermediate Level prime nrs includes count file size Time @@ -208,6 +226,7 @@ and a lot of disk. _10 < 1024 6 826 389 114 63 782 912(*) 2h 47'58"(*) (*) Before cpp crashed. +``` ## Copyright and CC BY-SA 4.0 License: diff --git a/2005/README.md b/2005/README.md index 263acab77..03c66fd95 100644 --- a/2005/README.md +++ b/2005/README.md @@ -1,109 +1,112 @@ -2005 marked the "The Eighteenth International Obfuscated C Code Contest" -======================================================================== +# [2005](/years.html#2005) marked the "The Eighteenth International Obfuscated C Code Contest" -Standard IOCCC stuff --------------------- +## Standard IOCCC stuff -Look at the README.md file for the given winner for information -on how to compile the winner and how to run the winning program. +Look at the `README.md` file for the given winner for information +on how to compile the entry and how to run the winning program. Look at the winning source and try to figure how it does what it does! You may then wish to look at the Author's remarks for even more details. The IOCCC has a web site and now has a number of international mirrors. -The primary site can be found at, +The primary site can be found at . -> - -Use make to compile entries. It is possible that on non-Un\*x / non-Linux -systems the makefile needs to be changed. See the Makefile for details. +Use `make(1)` to compile entries. It is possible that on non-Unix / non-Linux +systems the `Makefile` needs to be changed. See the `Makefile` for details. This year we included most of the information included by the submitters -in the README.md files. +in the `README.md` files. -Read over the makefile for compile/build issues. Your system may require -certain changes (add or remove a library, add or remove a #define). +Read over the `Makefile` for compile/build issues. Your system may require +certain changes (add or remove a library, add or remove a `#define`). Some ANSI C compilers are not quite as good as they should be. If -yours is lacking, you may need to compile using gcc instead of your +yours is lacking, you may need to compile using `gcc` instead of your local compiler. -Remarks on some of the entries ------------------------------- - -There were some outstanding entries that did not win. Unfortunately -some very good entries lost because they: - -+ depended too much on non-portable side effects in expressions; - -+ depended too much on a particular byte order; - -+ required the use of a special script, data file or pseudo-machine - language that was not supplied with the entry. - -We hope the authors of some of those entries will fix and re-submit -them for the next IOCCC. +## Remarks on some of the entries We believe you will be impressed with this year's winners. In particular: -+ The Abuse of the rules used local dictionary data to get around the -size limit. ++ The [Abuse of the rules](klausler/klausler.c) used local dictionary data to +get around the size limit. -+ The Most beauteous visuals made cleaver use of {}'s and whitespace in their source code and during execution. ++ The [Most beauteous visuals](vince/vince.c) made clever use of `{}`s and +whitespace in their source code and during execution. -+ The most circuitous walk entry is just amazing. ++ The [Most circuitous walk](vik/vik.c) entry is just amazing. -+ The Best game makes full use of its single function. ++ The [Best game](toledo/toledo.c) makes full use of its single function. -+ The Best emulator may allow you to re-connect to your first PET. ++ The [Best emulator](sykes) may allow you to reconnect to your first +[PET](https://en.wikipedia.org/wiki/Commodore_PET). -+ Our Best of Show this year was simply (or non-simply) the best! ++ Our [Best of Show](persano/persano.c) this year was simply (or non-simply :-) ) the best! -+ (And we need only mention (parenthetically speaking) that the best use of parenthesis is self re-producing). ++ (And we need only mention (parenthetically speaking) that the best use of parenthesis is self reproducing). -+ The most sonorous output might sound like a good idea. ++ The [Most sonorous output](jetro/jetro.c) might `sound` :-) like a good idea. -+ The Best 2D puzzle takes editorial license with expressions as well as the -with the vi editor. ++ The [Best 2D puzzle](giljade/giljade.c) takes editorial license with expressions as well as the +with the [vi editor](https://en.wikipedia.org/wiki/Vi). -+ The Most ambiguous language winner is really a C program. ++ The [Most ambiguous language](chia/chia.c) winner is really a C program. -+ The superfluous output winner is simply Voronoilific! ++ The [Most superfluous output](boutines/boutines.c) winner is simply +[Voronoi](Voronoi)-lific! -+ Try not to have your sense of good coding offended by the Most -discourteous interpreter winner. ++ Try not to have your sense of good coding offended by the [Most +discourteous interpreter](timwi/timwi.c) winner. -+ The Best use of the www doesn't include those letters ++ The [Best use of the www](mynx/mynx.c) doesn't include those letters. -+ You will be puzzled by Best 3D puzzle winner, we are sure! ++ You will be puzzled by the [Best 3D puzzle](anon/anon.c) winner; we are sure! -+ The Most ingenious puzzle solution might puzzle you more while it ++ The [Most ingenious puzzle solution](aidan/aidan.c) might puzzle you more while it puzzles out some puzzles: all in a puzzling way! :-) +### Remarks on some of the losing entries -Final Comments --------------- +There were some outstanding entries that did not win. Unfortunately +some very good entries lost because they: -Please feel free to send us comments and suggestions about the -competition, this README or anything else that you would like to see in -future contests. ++ depended too much on non-portable side effects in expressions; and/or + ++ depended too much on a particular byte order; and/or + ++ required the use of a special script, data file or pseudo-machine + language that was not supplied with the entry. + +We hope the authors of some of those entries will fix and resubmit +them for the next IOCCC. + + +## Final Comments + +Please feel free to send us comments and suggestions about the competition, this +[README.md](README.md) or anything else that you would like to see in future +contests. If you use, distribute or publish these entries in some way, please drop us a line. We enjoy seeing who, where and how the contest is used. If you have problems with any of the entries, AND YOU HAVE A FIX, please -send us the fix (patch file or the entire changed file). +send us the fix please submit your fixes fix as a [GitHub pull +request](https://github.com/ioccc-src/temp-test-ioccc/pulls). -For the latest information on how to contact the IOCCC Judges please visit +We will be happy to credit those who submit successful [GitHub pull +requests](https://github.com/ioccc-src/temp-test-ioccc/pulls) in the entry's +`README.md`. -> -For news of the next contest watch: +For the latest information on how to contact the [IOCCC +Judges](https://www.ioccc.org/judges.html) please visit +. -> +For news of the next contest watch . =-= diff --git a/2005/aidan/.gitignore b/2005/aidan/.gitignore index b717d985a..760a4c360 100644 --- a/2005/aidan/.gitignore +++ b/2005/aidan/.gitignore @@ -1 +1,2 @@ aidan +aidan.alt diff --git a/2005/aidan/Makefile b/2005/aidan/Makefile index 9c43a1a1a..1198df15a 100644 --- a/2005/aidan/Makefile +++ b/2005/aidan/Makefile @@ -113,8 +113,8 @@ DATA= blank.sudoku insane1.sudoku insane2.sudoku insane3.sudoku insane4.sudoku \ insane5.sudoku tough1.sudoku wp.sudoku TARGET= ${PROG} # -ALT_OBJ= -ALT_TARGET= +ALT_OBJ= ${PROG}.alt.o +ALT_TARGET= ${PROG}.alt ################# diff --git a/2005/aidan/README.md b/2005/aidan/README.md index e9e08d3ce..e1d8a9c84 100644 --- a/2005/aidan/README.md +++ b/2005/aidan/README.md @@ -1,8 +1,8 @@ # Most ingenious puzzle solution - Aidan Thornton - United Kingdom - makomk@lycos.co.uk +Aidan Thornton +United Kingdom + ## To build: @@ -14,12 +14,23 @@ make ```sh ./aidan < puzzle + +./aidan seed ``` +where `seed` is a number. + +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed the test script, +described by the author in their remarks, to refer to the proper compiled +program (it's hardcoded) which was never done which broke the script. Thank you +Cody! + ## Try: ```sh ./aidan < insane1.sudoku + +./aidan 42 ``` ## Judges' remarks: @@ -27,36 +38,48 @@ make Are you puzzled about puzzles? This entry might puzzle you more while it puzzles out some puzzles: all in a puzzling way! -Goto the source and notice the lack of functions. Jump -to the switch statement. And if you think you can puzzle -it out better, try solving insane1.sudoku all by yourself! +`Goto` the source and notice the lack of functions. Jump +to the `switch` statement. And if you think you can puzzle +it out better, try solving [insane1.sudoku](insane1.sudoku) all by yourself! + +NOTE: some of the files listed below by the author were either removed or +renamed. The removed file in question was a tarball but the files were extracted +into the directory instead. These files were added to the list. We also removed +the README.md which was at one point named `sudoku-sf.txt`. The author submitted +the program as `sudoku-sf.c` which was renamed and changed in their comments. + ## Author's remarks: -This program can solve a type of logic puzzle known as a Sudoku, and also -generate new ones. (Apparently, the puzzle is known as Number Place in the US, -but we in the UK got it via Japan, where it's quite common in magazines, etc. -These things happen sometimes.) +This program can solve a type of logic puzzle known as a +[Sudoku](https://en.wikipedia.org/wiki/Sudoku), and also +generate new ones. ### Contents - * build file: build.txt - you don't need this - * program file: sudoku-sf.c - sudoku solver and generator - * remarks file: sudoku-sf.txt - this file - * info file: test-su.perl - optional test script (written for Perl5) - * info file: eg-sudoku.tar - various assorted example sudokus +* build file: build.txt - you don't need this +* program file: [aidan.c](aidan.c) - sudoku solver and generator +* test suite: [test-su.perl](test-su.perl) - optional test script (written for Perl5) +* sudoku file: [blank.sudoku](blank.sudoku) +* sudoku file: [insane1.sudoku](insane1.sudoku) +* sudoku file: [insane2.sudoku](insane2.sudoku) +* sudoku file: [insane3.sudoku](insane3.sudoku) +* sudoku file: [insane4.sudoku](insane4.sudoku) +* sudoku file: [insane5.sudoku](insane5.sudoku) +* sudoku file: [tough1.sudoku](tough1.sudoku) +* sudoku file: [wp.sudoku](wp.sudoku) -**XXX - now the tar file includes the test script and the examples** Yes, the test suite really is 5 times larger than the actual program. You **did** say this was a parody of the software development process... -> **IMPORTANT!** -> -> test.perl expects the sudoku-sf executable to be `./sudoku-sf`. If you rename -> it, please change the definition of $sf_exe to the new name -> -> **IMPORTANT!** +### IMPORTANT + +[test.perl](test-su.perl) expects the `sudoku-sf` executable to be +`./sudoku-sf`. If you rename it, please change the definition of `$sf_exe` to the +new name. + +> Judges' note: this was done. ### Legal blurb @@ -70,14 +93,13 @@ it as you wish, though please give me credit. ### What is a sudoku? (If you know, feel free to skip this section. Get more details from [the -wikipedia entry]) - - [the wikipedia entry]: http://en.wikipedia.org/wiki/Sudoku +wikipedia entry](http://en.wikipedia.org/wiki/Sudoku)) A sudoku is a type of logic puzzle. You are given a grid of 9x9 boxes, some of which contain digits. This is divided into nine 3x3 boxes, e.g. (from the Wikipedia article - fairly easy): +``` . . . | 1 . . | 7 4 . . 5 . | . 9 . | . 3 2 . . 6 | 7 . . | 9 . . @@ -89,23 +111,28 @@ Wikipedia article - fairly easy): . . 4 | . . 7 | 3 . . 7 3 . | . 2 . | . 6 . . 6 5 | . . 4 | . . . +``` You have to fill in the remaining boxes so that each row, column, and smaller box contains all of the digits 1-9. That's all the information I needed to figure out how to solve them, but there's a useful tutorial on -, which is roughly affiliated with the Daily -Telegraph (a UK newspaper). +, which is roughly affiliated with the [Daily +Telegraph](https://www.telegraph.co.uk/), a UK newspaper. Now, with modern computers this **can** be solved using brute force, e.g.: - #include /* sudoku-bfi.c */ - #define S(t) for(n=0;n<9;v[n++]=0);for(n=0;n<81;n++)if(i[n]){z=1<80)goto - d;for(n=p;i[++p];);s[p]=n;i[p]=1;goto f;d:z=p<81;printf("\n%s!\n\n",z?"Fail": - "Success");for(n=0;n<81;){p=i[n];printf("%c %s",(p?p|48:'.'),(++n%3?"":n%9?"| " - :n%27?"\n":n%81?"\n------+-------+------\n":"\n\n"));}return z;} +```c +#include /* sudoku-bfi.c */ +#define S(t) for(n=0;n<9;v[n++]=0);for(n=0;n<81;n++)if(i[n]){z=1<80)goto +d;for(n=p;i[++p];);s[p]=n;i[p]=1;goto f;d:z=p<81;printf("\n%s!\n\n",z?"Fail": +"Success");for(n=0;n<81;){p=i[n];printf("%c %s",(p?p|48:'.'),(++n%3?"":n%9?"| " +:n%27?"\n":n%81?"\n------+-------+------\n":"\n\n"));}return z;} +``` + +> Judges' note: this was added as [aidan.alt.c](aidan.alt.c). That isn't the approach I've used; it's slow (particularly in worst-case or nearly so scenarios), inelegant, and not a good starting point for sudoku @@ -116,6 +143,7 @@ hopefully more reliably). Oh, and if you think that example sudoku is too easy, try this one (which my program generated): +``` --- insane1.sudoku -- . . 4 | . . . | . 5 6 5 . . | . 7 2 | . . . @@ -128,56 +156,64 @@ program generated): . 5 . | 2 . 1 | 4 . 8 3 . . | . . . | . . . . . . | . . . | . 6 1 +``` Be warned - it's evil! (I certainly haven't been able to solve it by hand. The -brute-force program given above, sudoku-bfi.c, also has trouble - it took 66 -seconds to solve it - but probably for different reasons. That's the worst -performance I've had from brute-force so far!) +brute-force program given above, `sudoku-bfi.c` ([aidan.alt.c](aidan.alt.c)), +also has trouble - it took 66 seconds to solve it - but probably for different +reasons. That's the worst performance I've had from brute-force so far!) ### Usage #### Building - cc -o sudoku-bf sudoku-bf.c +```sh +cc -o sudoku-sf sudoku-sf.c +``` --- or, if using gcc, try -- +or, if using gcc, try: - gcc -O2 -Wall -Wextra -ansi -pedantic-errors -o sudoku-sf sudoku-sf.c +```sh +gcc -O2 -Wall -Wextra -ansi -pedantic-errors -o sudoku-sf sudoku-sf.c +``` --- or, if using gcc and feeling lazy -- - - sh build.txt #### Testing (optional) - perl ./test-su.perl +```sh +perl ./test-su.perl +``` Note that this requires Perl 5 (I use 5.8.5, earlier versions untested) and is somewhat slow (should take under a minute on a fairly modern PC - try -appending "-n 0" if you're in a hurry). I wrote it mostly for my own benefit, +appending `-n 0` if you're in a hurry). I wrote it mostly for my own benefit, really. #### Solving - ./sudoku-sf < somefile.txt +```sh +./aidan < somefile.txt +``` Input should be the numbers of each row in turn. Empty spaces can be -represented as a period (.) or zero (0). Other characters are ignored, so you +represented as a full stop (.) or zero (0). Other characters are ignored, so you can cut-and-paste either example sudoku from above into a file and feed that in. The program has coped with every input I've thrown at it so far, including -an empty grid. +an [empty grid](blank.sudoku). Output consists of the problem, then the solution, then a message of success/failure. -`./sudoku-sf U` (capital U), may also be useful, or perhaps not. It only took +`./aidan` (capital `U`), may also be useful, or perhaps not. It only took an extra 15 bytes of (very simple) code to add, so it doesn't really matter to -me. (It's the same as the normal mode for most input you're likely to feed in, +me. (It's the same as the normal mode for most input you're likely to feed it, though slightly slower. See if you can figure out what it does.) #### Generating - ./sudoku +```sh +./sudoku +``` Output is a blank grid, then the solution, then the problem. There's no control over the difficulty. Sorry. However, all generated sudokus should have @@ -188,21 +224,21 @@ exactly one solution - if one doesn't, that's a bug. Fast enough. Solving and generating are practically instant on my 1Ghz Duron. Of course, there could be some cases which take longer... -More precisely - 400 random sudokus are generated and solved in about 45 -seconds in tests on my PC (1Ghz Duron, gcc 3.4.1, -O2 optimisation - takes -about 60 seconds with no optimisation). If that isn't fast enough, what on -Earth are you doing with it? +More precisely - 400 random sudokus are generated and solved in about 45 seconds +in tests on my PC (1Ghz Duron, gcc 3.4.1, `-O2` optimisation - takes about 60 +seconds with no optimisation). If that isn't fast enough, what on Earth are you +doing with it? ### Bugs None known - hopefully I've worked out all the major ones. Nothing has come up -in testing since the last bugfix, but what does that mean? +in testing since the last bug fix, but what does that mean? Tested on: - - gcc 3.4.1-3mdk, Linux/x86 +- `gcc 3.4.1-3mdk`, Linux/x86 - *RETEST* Borland C 4.5, 16-bit DOS .exe (small memory model) +*RETEST* Borland C 4.5, 16-bit DOS .exe (small memory model) I don't count the fact that it first prints a blank grid whenever asked to generate a sudoku as a bug - just a minor quirk. The fix is slightly awkward @@ -211,17 +247,17 @@ important. ### Missing Features - * No control over the difficulty of generated sudokus - they vary from easy -to hair-tugging near-impossibility. Solver beware. Seeing as apparently one -program [took six years], I'm in no hurry. +* No control over the difficulty of generated sudokus - they vary from easy to +hair-tugging near-impossibility. Solver beware. Seeing as apparently one program +[took six years](http://news.bbc.co.uk/1/hi/magazine/4469719.stm), I'm in no +hurry. - [took six years]: http://news.bbc.co.uk/1/hi/magazine/4469719.stm - * Some sort of curses-based UI to let you solve interactively might be cool, +* Some sort of curses-based UI to let you solve interactively might be cool, but I don't feel like learning curses just for this. Besides, I spent enough of the time swearing as it is. - * If you mistype a sudoku (e.g. from a paper/magazine) - and you will it +* If you mistype a sudoku (e.g. from a paper/magazine) - and you will - it can't help you figure out where the mistake is, sadly. ### Portability @@ -231,8 +267,10 @@ least 32. (No, that isn't a typo - I did say 15, not 16). Also requires that cpp can properly handle something like: - #define foo(x,y) x y - foo(bar,) +```c +#define foo(x,y) x y +foo(bar,) +``` Apparently, a few can't (ANSI C specifically doesn't require that this works, though it usually does). Unfortunately, I didn't discover this issue until too @@ -243,35 +281,35 @@ of obscure compiler limitations" section, so I'm figuring it's quite unusual.) Some when compiled with `gcc -Wall -Wextra -ansi -pedantic`: - * The left-hand operand of a comma has no effect in two places - * Parentheses are suggested around a + in an operand of & in the "i" macro +* The left-hand operand of a comma has no effect in two places +* Parentheses are suggested around a `+` in an operand of `&` in the `i` macro definition. Borland C also spots some code in expressions which has no effect, and some -uses of '=' where you'd expect a comparison operator. +uses of `=` where you'd expect a comparison operator. ### Obfuscation Let's see now: - * Squint-inducing variable naming - * Slightly odd `#defines` (which will be cleaned up by cpp + a code - beautifier, but see the next item) - * No functions but main() - all code reuse via #defines, or by various other - methods (usually somewhat icky ones). This wasn't deliberate - it just ended - up that way somehow... - * Gotos from everywhere to everywhere else - * A slightly... interesting switch statement. - * Generally odd flow of control (see above items) - * Plenty of bit-twiddling - * To save space, no 'A'-style char constants - hard-coded numbers are used. - (There's one, but it isn't used to make things **clearer**) - * `array[index]` notation, because: - - a) it's traditional - - b) take a look at how the s and N(I,l) macros are used - * various other little things not worth mentioning +* Squint-inducing variable naming. +* Slightly odd `#defines` (which will be cleaned up by `cpp` + a code +beautifier, but see the next item). +* No functions but `main()` - all code reuse via `#define`s, or by various other +methods (usually somewhat icky ones). This wasn't deliberate - it just ended up +that way somehow... +* `goto`s from everywhere to everywhere else. +* A slightly... interesting `switch` statement. +* Generally odd flow of control (see above items). +* Plenty of bit-twiddling. +* To save space, no `'A'`-style char constants - hard-coded numbers are used. +(There's one, but it isn't used to make things **clearer**). +* `array[index]` notation, because: + - it's traditional + - take a look at how the `s` and `N(I,l)` macros are used +* various other little things not worth mentioning. -So basically, just what you'd normally expect in an IOCCC entry +So basically, just what you'd normally expect in an IOCCC entry. ## Copyright and CC BY-SA 4.0 License: diff --git a/2005/aidan/aidan.alt.c b/2005/aidan/aidan.alt.c new file mode 100644 index 000000000..3946caeaf --- /dev/null +++ b/2005/aidan/aidan.alt.c @@ -0,0 +1,9 @@ +#include /* sudoku-bfi.c */ +#define S(t) for(n=0;n<9;v[n++]=0);for(n=0;n<81;n++)if(i[n]){z=1<80)goto +d;for(n=p;i[++p];);s[p]=n;i[p]=1;goto f;d:z=p<81;printf("\n%s!\n\n",z?"Fail": +"Success");for(n=0;n<81;){p=i[n];printf("%c %s",(p?p|48:'.'),(++n%3?"":n%9?"| " +:n%27?"\n":n%81?"\n------+-------+------\n":"\n\n"));}return z;} + diff --git a/2005/aidan/test-su.perl b/2005/aidan/test-su.perl index c0c2d3eee..ebe9477bd 100755 --- a/2005/aidan/test-su.perl +++ b/2005/aidan/test-su.perl @@ -3,7 +3,7 @@ use warnings; use IPC::Open2; -my $sf_exe = "./sudoku-sf"; # location of sudoku-sf executable +my $sf_exe = "./aidan"; # location of sudoku-sf executable my $vflg=0; my $gcmd=$sf_exe; my $scmd=$sf_exe; my $gcnt=400; my $soff=2; my $fbad=1; my $ffile=1; diff --git a/2005/anon/.gitignore b/2005/anon/.gitignore index 2beb3546b..b6307fc00 100644 --- a/2005/anon/.gitignore +++ b/2005/anon/.gitignore @@ -1 +1,2 @@ anon +anon.alt diff --git a/2005/anon/Makefile b/2005/anon/Makefile index bec3a11ee..081a8cbdb 100644 --- a/2005/anon/Makefile +++ b/2005/anon/Makefile @@ -112,8 +112,8 @@ OBJ= ${PROG}.o DATA= TARGET= ${PROG} # -ALT_OBJ= -ALT_TARGET= +ALT_OBJ= ${PROG}.alt.o +ALT_TARGET= ${PROG}.alt ################# @@ -130,6 +130,10 @@ all: data ${TARGET} ${PROG}: ${PROG}.c ${CC} ${CFLAGS} $< -o $@ ${LIBS} +${PROG}.alt: ${PROG}.c + ${CC} ${CFLAGS} -DNO_STTY $< -o $@ ${LIBS} + + # alternative executable # alt: data ${ALT_TARGET} diff --git a/2005/anon/README.md b/2005/anon/README.md index de908f8e4..a6148ce13 100644 --- a/2005/anon/README.md +++ b/2005/anon/README.md @@ -1,6 +1,6 @@ # Best 3D puzzle - Anonymous +Anonymous ## To build: @@ -8,6 +8,9 @@ make ``` +NOTE: if your shell does not support `stty` then see the alternate version +described in the section below. + ## To run: ```sh @@ -21,20 +24,59 @@ make ./anon 3 3 3 ``` +### Alternate version: + +The author stated that if `stty` does not work right on your system you can +compile it differently so that the program does not use `stty`. +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) set this up so that one +need not update the [Makefile](Makefile). There's a fun thing here that will be +mentioned below as well. Thank you Cody! To use this version: + +```sh +make alt +``` + +Use `anon.alt` as you would `anon`. + +### INABIAF - it's not a bug it's a feature! :-) + +After a very large number of moves this program will deliberately force itself +to destroy its runtime stack. This is the author's way to prevent you from being +frustrated (which might happen as it likes to create unsolvable puzzles just to +hook you) and spending too much time playing. :-) + +If you want to see this in action you can easily do this with the alt version: + +```sh +yes 'please crash on me :-)' | ./anon.alt 4 4 +``` + +What happens if you specify a larger board? For instance: + +```sh +yes 'please crash on me :-)' | ./anon.alt 10 10 10 +``` + +If you specify more than three args the program might also crash or do +something strange. This might also happen if you specify excessively large board +dimensions. Try `100 100 100` for instance and see what happens! + + ## Judges' remarks: -Taking the 4x4 board with 15 tiles to a whole new level, this entry -takes this puzzle to a whole new dimension! While you puzzle out -this puzzle, we invite you to take a good LONG look how and WHY -main is recursively called and how the run-time stack is used. +Taking the 4x4 board with 15 tiles to a whole new level, this entry takes this +puzzle to a whole new dimension! While you puzzle out this puzzle, we invite +you to take a good LONG look how and WHY `main()` is recursively called and how +the runtime stack is used. ## Author's remarks: ### ABOUT THE GAME ITSELF -Remember Sam Loyd's Fifteen Puzzle? It consists of a 4x4 board with 15 tiles -numbered 1 to 15, and an empty spot. The goal of the game is to slide the -tiles around without lifting them off the board, so that they become sorted. +Remember Sam Loyd's [Fifteen Puzzle](https://en.wikipedia.org/wiki/15_puzzle)? +It consists of a 4x4 board with 15 tiles numbered 1 to 15, and an empty spot. +The goal of the game is to slide the tiles around without lifting them off the +board, so that they become sorted. Well, that was then. This program is the 21st century version of the Fifteen Puzzle: not only does it allow arbitrary board sizes, it also supports _3D_ @@ -49,52 +91,58 @@ For example, to play the original version of the Fifteen Puzzle: ./anon 4 4 ``` -To play in a 3D board, do something like this: +To play with a 3D board, do something like this: ```sh ./anon 3 3 3 ``` -**[WARNING: do NOT run the program with more than 3 command-line arguments. +**WARNING: do NOT run the program with more than 3 command-line arguments. This will trigger a bug that will cause it to crash or do something strange. -:-)]** +:-)** Also, resist the temptation to create very large puzzles. The program does not attempt to resize your terminal for you, and will produce confusing output. It may also crash on you if you insist on running it with excessively large board dimensions. :-) (10x10x10 is considered a safe upper limit.) -The empty space on the board is represented by a space filled with '#' +The empty space on the board is represented by a space filled with `#` characters instead of digits. To slide the tiles around, use the following keys: - i | Slide the tile above the current empty space downwards. - j | Slide the tile to the left of the current empty space to the right. - k | Slide the tile below the current empty space upwards. - l | Slide the tile to the right of the current empty space to the left. - o | Slide the tile behind the current empty space forwards. - n | Slide the tile in front of the current empty space backwards. +``` +i | Slide the tile above the current empty space downwards. +j | Slide the tile to the left of the current empty space to the right. +k | Slide the tile below the current empty space upwards. +l | Slide the tile to the right of the current empty space to the left. +o | Slide the tile behind the current empty space forwards. +n | Slide the tile in front of the current empty space backwards. +``` To quit the game: - q | Quit the game. +``` +q | Quit the game. +``` Note that, for example, sliding the tile above the current empty spot downwards will fill up the empty spot, and create a new empty spot above where the current empty spot was. Hence, you could think of the movement keys in terms of how they effectively "move" the empty spot: - i | Move empty spot up - j | Move empty spot left - k | Move empty spot down - l | Move empty spot right - n | Move empty spot forwards - o | Move empty spot backwards +``` +i | Move empty spot up +j | Move empty spot left +k | Move empty spot down +l | Move empty spot right +n | Move empty spot forwards +o | Move empty spot backwards +``` **NOTE:** as a measure of alleviating counter-productivity due to addiction to this game, particularly for those hardcore gamers who insist on solving a 10x10x10 puzzle during work hours, and also to give an upper bound to user -frustration when the program generates an impossible puzzle (which it does +frustration when the program generates an unsolvable puzzle (which it does roughly half the time, just to hook you), the program will, after a very large number of moves (which is system-specific) terminate itself by forcefully destroying its own runtime stack. This will result in a core dump and/or an @@ -113,7 +161,7 @@ operator precedence to accomplish some cool hacks. :-) However, there are no compiler errors. I have tested this with `gcc -pedantic -std=c99`. The program also uses `stty cbreak`. If this breaks on your system, compile it -with -DNO_STTY. The game interface will be a bit annoying (you will need to +with `-DNO_STTY`. The game interface will be a bit annoying (you will need to hit enter after every key), but it works. The game requires lots of space on the runtime stack space due to deep @@ -125,29 +173,29 @@ See spoilers below for more notes about portability. Clearly, the author is very, very confused. Although he has broken up the file into sections labelled with helpful headings, and although he has left ample -whitespace between all those #define's to make them easier to read, :-) and +whitespace between all those `#define`s to make them easier to read, :-) and although he has helpfully formatted the code with beautiful indentation, something is clearly very, very wrong. In fact, the closer you look at this code, the more you realize something is horribly wrong with it. For example, why is it that the first statement in -main() is a return? What do all those nested do-loops do? (pun intended) Why -is the first statement inside the first do-loop a mere integer literal? Why -are there such strange statements, like that empty string on line 64, or that -isolated || on line 67? +`main()` is a `return`? What do all those nested `do`-loops do? (pun intended) Why +is the first statement inside the first `do`-loop a mere integer literal? Why +are there such strange statements, like that empty string on line 65, or that +isolated `||` on line 68? But wait... why aren't any statements terminated by semicolons? Why is there only ONE semicolon in the entire program?! Why is the author opening nested -blocks by such strange things as || and (, and closing them by || and ))? The -for-loop isn't a for-loop! The do-loop isn't a do-loop! Or... are they? Well, -the for-loop is defined in terms of a while-loop. But wait, the while loop is -defined in terms of the do-loop. And the do-loop is defined in terms of ... +blocks by such strange things as `||` and `(`, and closing them by `||` and `))`? The +`for`-loop isn't a `for`-loop! The `do`-loop isn't a `do`-loop! Or... are they? Well, +the `for`-loop is defined in terms of a `while`-loop. But wait, the `while` loop is +defined in terms of the `do`-loop. And the `do`-loop is defined in terms of ... Huh??? -And that switch statement toward the end of the program... wait a minute, that's -not a switch statement! Why is a case defined in terms of a switch statement?! -And that initial return isn't a return! Well, it is... but not what you might -think! +And that `switch` statement toward the end of the program... wait a minute, +that's not a `switch` statement! Why is a `case` defined in terms of a `switch` +statement?! And that initial return isn't a return! Well, it is... but not what +you might think! Let's see if it all makes sense after we run it through CPP... @@ -156,17 +204,17 @@ than the one who wrote the original code. Unfortunately, unless you're a Lisp expert, it is probably easier to understand the program in its original form. (And even then.) But that's just so, so wrong... -The entire program consists of a single expression, returned from main(). -There are no if-statements, no for-loops or any looping or control constructs -besides the 'return', in spite of the misleading appearance of the original -source. :) Yes I know, this has been attempted before, using ?: and the bad -old comma operator. BUT this program does NOT use the ?: operator, and there +The entire program consists of a single expression, returned from `main()`. +There are no `if`-statements, no `for`-loops or any looping or control constructs +besides the `return`, in spite of the misleading appearance of the original +source. :) Yes I know, this has been attempted before, using `?:` and the bad +old comma operator. BUT this program does NOT use the `?:` operator, and there are only TWO comma operators in the entire program--and they are only there -because srand() and exit() return void. +because `srand()` and `exit()` return void. The entire program consists of a single boolean expression returned from -main(). Looping is achieved by recursion, of course, and branching is achieved -by exploiting short-circuit evaluation of boolean expressions. `:-)` +`main()`. Looping is achieved by recursion, of course, and branching is achieved +by exploiting short-circuit evaluation of boolean expressions. :-) But this is not all. @@ -192,7 +240,7 @@ on the following architectures: * ia64/linux * sparc64/linux -It probably will also compile and work on many (all?) other *nix platforms as +It probably will also compile and work on many (all?) other \*nix platforms as well. How does it achieve this incredible feat? ### SPOILER @@ -219,7 +267,7 @@ well. How does it achieve this incredible feat? . -(Read the following only if you give up figuring it out `:-)`) +(Read the following only if you give up figuring it out :-) ) . @@ -244,153 +292,160 @@ well. How does it achieve this incredible feat? The program (ab)uses an implicit assumption underlying practically all architectures, and that is that parameters to C functions are implicit local variables allocated on the runtime stack. This runtime stack is a contiguous -section of memory, and therefore, after N recursive calls of main() to itself, +section of memory, and therefore, after N recursive calls of `main()` to itself, there is enough room on the stack to store whatever the program desires, so long as it does not exceed the maximum stack size. -(Theoretically, the runtime stack doesn't **have** to be contiguous… but all +(Theoretically, the runtime stack doesn't **have** to be contiguous... but all current architectures that are worth consideration make this assumption. I submit that this implies this program is 100% portable, even though -theoretically it shouldn't even work in the first place.) `:-)` +theoretically it shouldn't even work in the first place.) :-) There are two types of architectures the program must handle: those that allocate the stack top-down, and those that allocate the stack bottom-up. The -program correctly detects this at run-time, and adjusts itself accordingly. +program correctly detects this at runtime, and adjusts itself accordingly. :-) (It is a simple matter of testing if the address of argc in a recursive call is greater or less than in the parent call.) To avoid having to handle issues of int sizes, memory alignment, what exactly is on the stack between successive locations of argc, etc., the program (ab)uses the fact that argc must necessarily be allocated on an aligned -address, and therefore, the range of memory between two argc's is aligned, and -therefore safe to use as an array of longs.[*] The program also compares the -pointers as (long*) pointers, so that it will not have to deal with mapping +address, and therefore, the range of memory between two `argc`s is aligned, and +therefore safe to use as an array of longs.[\*] The program also compares the +pointers as `long*` pointers, so that it will not have to deal with mapping bytes to larger types. The initial memory allocation is done by recursively -calling main() until there is enough space on the stack (the exact number of +calling `main()` until there is enough space on the stack (the exact number of recursive calls is, of course, architecture-dependent). -[*] long was chosen instead of int, in order to skirt around pointer-size +[\*] long was chosen instead of int, in order to skirt around pointer-size issues on architectures like ia64. It really can be made anything large enough to hold both ints and pointers. `:-)` After the stack is deemed to have grown deep enough to be a sufficiently long array (pun intended), the program begins its real code. It uses argc to keep -track of what it's supposed to be doing (since main() is the only function), -and argv to point to the base of this array (which is computed differently +track of what it's supposed to be doing (since `main()` is the only function), +and `argv` to point to the base of this array (which is computed differently based on how the architecture allocates the stack). Since this fills up the -only two variables in the program, everything else is stored in the MASS [**] +only two variables in the program, everything else is stored in the `MASS` [\*\*] array. -[**] for "Memory Allocated by Stack Smashing" `:-)` +[\*\*] for "Memory Allocated by Stack Smashing" `:-)` Note that from this point on, all bets are off as to what the contents of the -runtime stack are below the current recursive call to main(). We are +runtime stack are below the current recursive call to `main()`. We are overwriting frame pointers, return addresses, etc., with data. Hence, the program must never return from this call, otherwise it will crash horribly. -That's why I had to call exit() even though it meant I can no longer claim the +That's why I had to call `exit()` even though it meant I can no longer claim the program doesn't need the comma operator. :-) (I was going to skirt around the -issue by indirectly calling exit(), such as via bsearch() or raise(), but I +issue by indirectly calling `exit()`, such as via `bsearch()` or `raise()`, but I was getting too close to the size limit.) #### Some notes about the macros In spite of the frightening appearance, it is probably easiest to understand -the code in its original form. (Don't even try running 'indent' on it: on my +the code in its original form. (Don't even try running `indent` on it: on my system it chokes and complains about nesting errors.) -Most of the #define's are just to keep the code size down, due to the abusive +Most of the `#define`s are just to keep the code size down, due to the abusive amounts of type casting employed. The others define a bizarre "programming language" (in the crudest, most twisted sense of the word) that the author used to write this mess. -R(i) and W(i,j) are macros to read/write the i'th position of the MASS. +`R(i)` and `W(i,j)` are macros to read/write the `i`th position of the `MASS`. -A(i) retrieves the i'th command-line argument. This is slightly tricky, -because by the time the MASS is setup, we no longer have access to the -original values of argc and argv. So what is done is that the initial memory -allocation code will save argc and argv into positions 8 and 9 in the MASS -after the allocation. It does this by using argv, which at that time contains -a pointer to the top-level argc, to compute the location of the top-level -argv. This is done before the rest of the MASS is used, since otherwise they +`A(i)` retrieves the `i`th command-line argument. This is slightly tricky, +because by the time the `MASS` is setup, we no longer have access to the +original values of `argc` and `argv`. So what is done is that the initial memory +allocation code will save `argc` and `argv` into positions 8 and 9 in the `MASS` +after the allocation. It does this by using `argv`, which at that time contains +a pointer to the top-level `argc`, to compute the location of the top-level +`argv`. This is done before the rest of the `MASS` is used, since otherwise they may be overwritten. -do(x,y) has nothing to do with do-loops. `:-)` It defines a "state" in main(), -essentially, what to do when main() is called with argc containing a +`do(x,y)` has nothing to do with `do`-loops. :-) It defines a "state" in `main()`, +essentially, what to do when `main()` is called with `argc` containing a particular value. (This is why the user must never run the program with more -than 3 arguments. :-) The state number is x, and y is the code. The program's -boolean expression consists of a number of states &&'d together. Within each -state, it is assumed that statements are separated by ||. All statements are +than 3 arguments. :-) The state number is `x`, and `y` is the code. The program's +boolean expression consists of a number of states `&&`d together. Within each +state, it is assumed that statements are separated by `||`. All statements are assumed to evaluate to false. This makes it easy to write conditional -statements: "if (a) { b } ..." can simply be written "a && b || ...". All -states created by do(x,y) are assumed to evaluate to false. There is only 1 +statements: `if (a) { b } ...` can simply be written `a && b || ...`. All +states created by `do(x,y)` are assumed to evaluate to false. There is only 1 state which can return true or false: state 5, a "manually-implemented" state which determines whether the system uses top-down or bottom-up stack allocation. It's the only state that needs to return a value from the boolean -expression, since once the MASS is initialized any return value can simply be -stored in a well-known location in the MASS. +expression, since once the `MASS` is initialized any return value can simply be +stored in a well-known location in the `MASS`. -if(p,q,r,s) is, in fact, an if-statement. `:-)` It is equivalent to: +`if(p,q,r,s)` is, in fact, an if-statement. `:-)` It is equivalent to: - if (p) { q; r } else {s} +```c +if (p) { q; r } else {s} +``` -Why are q and r split up? Because it's cleaner (in whatever twisted sense of +Why are `q` and `r` split up? Because it's cleaner (in whatever twisted sense of the word that can be applied to an IOCCC entry) to implement using boolean expressions. Keep in mind that all statements are assumed to evaluate to -false. The proof that this macro in fact implements an if-then-else construct +false. The proof that this macro in fact implements an `if-then-else` construct is left as an exercise for the reader. -while(x,y,z) is actually a while-loop after all. `:-)` It implements the loop -using, of course, recursive calls to main(). However, this macro doesn't -actually run a while loop; it implements the loop in the state numbered x. It -is used for defining a while loop, which can then be called from another state -using f(x). (The reason we can't directly implement a while-loop inside -another state ought to be clear: we can't recursively call main() to enter +`while(x,y,z)` is actually a `while`-loop after all. :-) It implements the loop +using, of course, recursive calls to `main()`. However, this macro doesn't +actually run a `while` loop; it implements the loop in the state numbered `x`. It +is used for defining a `while` loop, which can then be called from another state +using `f(x)`. (The reason we can't directly implement a `while` loop inside +another state ought to be clear: we can't recursively call `main()` to enter into the middle of a state.) -However, it _is_ possible to implement a for-loop directly inside a state! The -for(s,i,x,y,z,Z) macro does exactly this. Well, actually, technically speaking +However, it _is_ possible to implement a `for`-loop directly inside a state! The +`for(s,i,x,y,z,Z)` macro does exactly this. Well, actually, technically speaking this macro can only be used as the last thing in a state, because it secretly closes the current state and opens a new one behind the programmer's back. -:-) Its intended usage is this: s is the state number for the loop body, and i -is the index variable (well, the index into the MASS of the index variable); x -and y-1 define the starting and ending values of i, and z is the loop body. Z -is the post-loop code in the current state. For example: +:-) Its intended usage is this: `s` is the state number for the loop body, and +`i` is the index variable (well, the index into the `MASS` of the index +variable); `x` and `y-1` define the starting and ending values of `i`, and `z` +is the loop body. `Z` is the post-loop code in the current state. For example: - for(s,i, 0, 10, - some_code , - other_code) +```c +for(s,i, 0, 10, +some_code , +other_code) +``` is equivalent to: - for (i=0; i<10; i++) { - some_code; - } - other_code; +```c +for (i=0; i<10; i++) { + some_code; +} +other_code; +``` Note the "wrong" indentation in the former: the author prefers to write it -that way, since the analogy to the usual for-loop is clearer. This is why it's +that way, since the analogy to the usual `for`-loop is clearer. This is why it's easier to understand the pre-CPP code, since after CPP, the macro reshuffles -some_code after other_code so that it can close the current state and define +`some_code` after `other_code` so that it can close the current state and define the one containing the loop body. (Have I told you that the author of this program is horribly, horribly, confused? :-) This confusion also shows up in the superficial appearance of the program, which heavily suffers from wrong indentation.) -In spite of all appearances, switch() really is just a shorthand macro for +In spite of all appearances, `switch()` really is just a shorthand macro for reducing code size. The evil choice of macro name is just to instill more -confusion into the would-be decipherer of this entry. :-) After all, case() -really _is_ the equivalent of a case statement, implemented using &&, and -conveniently encapsulating code common to the cases in the only switch- +confusion into the would-be decipherer of this entry. :-) After all, `case()` +really _is_ the equivalent of a case statement, implemented using `&&`, and +conveniently encapsulating code common to the cases in the only `switch` statement in the program, which is the code that decides what to do with a -keypress. What could be more fun than to define such a case in terms of a -switch? :-) +key press. What could be more fun than to define such a case in terms of a +`switch`? :-) Finally, for those who give up deciphering this horribly confused code, here -are the mappings of various locations of the MASS to their usage in the +are the mappings of various locations of the `MASS` to their usage in the program, and what the various state numbers are meant to do: #### MASS usage map +``` 0 | Function return value 1 | Function argument 1 2 | Function argument 2 @@ -410,19 +465,21 @@ program, and what the various state numbers are meant to do: 18 | Scratch register used by state 18 :-) 31 | field width for printing tiles 32 | Start of board data +``` (**CAVEAT:** not all of these mappings ended up in the final version of the program, mainly due to size limitations which entailed the trimming off of a lot of neat features in the game. It is left as an exercise for the reader to figure out which of these are actually used.) -Note that argv and argc necessarily needs to stay away from lower indices of -the MASS, because otherwise they may overwrite their original values when the +Note that `argv` and `argc` necessarily need to stay away from lower indices of +the `MASS`, because otherwise they may overwrite their original values when the memory allocation code saves them. Index 8 is deemed "safe enough". (It seems to be on all tested architectures.) #### State number assignments +``` 1 | showhelp 2 | showhelp 3 | is 2D: start init @@ -439,9 +496,10 @@ to be on all tested architectures.) 17 | inner loop of 16. 18 | main loop 19 | checkwin() loop +``` Note that some of the manually-implemented states (those not implemented by -do()) respond to multiple state numbers. Also note that states 1-4 +`do()`) respond to multiple state numbers. Also note that states 1-4 conveniently correspond to what the program should do when 1-4 arguments are given at the command-line. :-) diff --git a/2005/anon/anon.c b/2005/anon/anon.c index 96908d1fd..555534af1 100644 --- a/2005/anon/anon.c +++ b/2005/anon/anon.c @@ -52,127 +52,125 @@ /* Main program */ -int main(int a, P b) { - return(1>>1^1, M(6+!!M(5,C),C)) +int +main(int a, P b) +{ + return (1 >> 1 ^ 1, M(6 + !!M(5, C), C)) + do + ( + 13, + pr("\x1b[;H") || - do( - 13, - pr("\x1b[;H")|| + for (14, 4, 0, BS, !X(4) && pr( + "%*s", + I(l - Y(4)), + "" + ) + || - for(14,4,0,BS,!X(4)&&pr( - "%*s", - I(l-Y(4)), - "" - ) + if (TL(4), pr( + "%*ld", I + R(31), + TL(4)), 0, + pr("%*.*s", I + R(31), + I R(31), "#####") + ) + if (X(4) == w - 1, pr("\n"), 0, pr("%*s", I(l + 1), "")) ( + (R(4) + 1) % (w * l) == 0 && l > 1) && + pr("\n"), 0)) + do + ( + 1 & ~1, + pr("Syntax: %s []\n", b[0]) || f(15) + ) ((a & ~1) + - 6 || D >> 12 + && (*(p(T(C, b)) + 8) = *p(Q(b) + (Q(&b) - Q(C))) + ) + && (*(p(T(C, b)) + 9) = *p(b)) && M( + 8, T(C, b)) + || - || + f(a)) && + do + ( + 8, + if (R(9) & 1, H(1) H( + 2) 0, W(14, + l) W(13, 1) 0, + H(1 + ) + H(2) + H(3) + 0) (srand(time(0)), 0 + ) || for (9, 4, 0, BS, f(16) + || W(R(4) + 32, R(0)) ! R(0) && W(15, R(4)) 0, - if(TL(4),pr( - "%*ld",I - R(31), - TL(4)),0, - pr("%*.*s",I - R(31), - I R(31),"#####") - ) - if(X(4)==w-1 , pr("\n"),0 , pr("%*s", I(l+1), "")) ( - (R(4)+1)%(w*l)==0 && l>1)&& - pr("\n"),0)) - do( - 1&~1, - pr("Syntax: %s []\n", b[0])||f(15) - )((a&~1) + W( + 31, + snprintf(A(0), 1, "%ld", BS)) + S1 pr("\x1b[2J") || + f(13) + || - -6||D>>12 - &&(*(p(T(C,b))+8)=*p(Q(b)+(Q(&b)-Q(C))) - ) - - &&(*(p(T(C,b))+9) = *p(b))&&M( - 8,T(C,b)) - || + f(18) || + f(15) + )) + do + ( + 16, W(0, rand() % BS + ) W(1, 0) + for (17, 5, 0, R(4), !( + TL( + 5) - R(0)) && !( + W(1, 1) + W(5, R(4) - 1) + 0), R(1) && f(16)) + ) + do + ( + 18, W(0, 0 + ) for (19, 4, 0, BS, TL(4) - (R(4) + 1) + % BS && ( + W(0, 1) + W(4, BS - 1 + ) 0) || 0, !R(0) && - f( a) )&&do( - 8, - if(R(9)&1,H(1)H( - 2 ) 0,W(14, - l)W(13,1)0, - H(1 - ) + pr( + "You win!\n" + ) + || + R(0) && ( + W(a, getchar()) + case ('i', + 0 < Z(15), + -w * l) + case ('j', + 0 < X(15), + -1) + case ('k', + Z(15) < h - 1, + w * l) + case ('l', + X(15) < w - 1, + 1) + case ('n', + Y(15) < l - 1, + w) + case ('o', + 0 < Y(15), -w + ) + R(a) == 'q' && ! - H(2) - H(3) - 0)(srand(time(0)),0 - ) ||for(9,4, 0,BS, f(16) - - || W(R(4)+32,R(0))!R(0) && W(15,R(4) )0, - - W( - 31, - snprintf(A(0),1,"%ld",BS)) - S1 pr("\x1b[2J") || - f(13) - || - - f(18) || - f(15) - )) - - do( - 16,W(0,rand()%BS - ) W(1,0) - - for(17, 5, 0,R(4),! ( - TL( - 5)-R(0))&&! ( - W(1,1) - W(5,R(4)-1) - 0),R(1)&&f(16)) - ) - - do( - 18,W(0,0 - ) for(19,4,0,BS, TL(4)-(R(4)+1) - - %BS&& ( - W(0,1) - W(4,BS-1 - ) 0)||0,!R(0) && - - pr( - "You win!\n" - ) - || - R(0)&& ( - W(a,getchar()) - case('i', - 0 ## To build: @@ -12,65 +12,86 @@ make ## To run: -You will need an [SVG] viewer. Look here to find some [SVG Viewer Implementations]. +You will need an [SVG](https://www.w3.org/TR/SVG11/expanded-toc.html) viewer. +Look here to find some [SVG Viewer +Implementations](https://www.w3.org/Graphics/SVG/WG/wiki/Implementations). - [SVG]: http://www.w3.org/Graphics/SVG/ - [SVG Viewer Implementations]: http://wiki.svg.org/Viewer_Implementations - -The following will create an SVG file: +The following will create an `SVG` file: ```sh -perl -e 'map{print rand," ",rand,"n";}(1..20);' | ./boutines > test.svg +ruby -e '20.times{puts "#{rand} #{rand}"}' | ./boutines > test.svg ``` ## Try: +After running the above, use [ImageMagick](https://imagemagick.org/index.php)'s +`convert` tool to convert the image to a png file: + ```sh -perl -e 'map{print rand," ",rand,"n";}(1..20);' | ./boutines > test.svg +convert test.svg test.png ``` +and then open it with your preferred graphics viewer or editor. + +If you have a program that opens +[SVG](https://www.w3.org/TR/SVG11/expanded-toc.html) files then you could open +the `test.svg` file directly. An example program is +[Inkscape](https://inkscape.org). See the +[list](https://www.w3.org/Graphics/SVG/WG/wiki/Implementations) cited above for +others. + + ## Judges' remarks: -Can you explain the author's remark "[generated files] are not as scalable as their name suggests"? +Can you explain the author's remark "[generated files] are not as scalable as +their name suggests"? ## Author's remarks: _In memory of my father Pierre Boutines-Vignard._ -### Walkthrough +### Walk-through My program works as follows: -**Input** -> a list of 2D points in the unit square +#### Input -**Output** -> a Voronoi diagram of the set as an [SVG] stream +A list of 2D points in the unit square. + +#### Output + +A [Voronoi diagram](https://en.wikipedia.org/wiki/Voronoi_diagram) of the set as +an [SVG](https://www.w3.org/TR/SVG11/expanded-toc.html) stream. This will possibly save a compressed SVG file and may be useful: - ./boutines | gzip > result.svgz +```sh +./boutines | gzip > result.svgz +``` Input consists of a list of floating points values separated by whitespaces -(ranging preferably in [0,1]). Alternating an horizontal coordinate, a +(ranging preferably in `[0,1]`). Alternating a horizontal coordinate, a whitespace then the other coordinate (pointing downwards in the resulting -graph) and a newline will just go fine : +graph) and a newline will just go fine: - 0 0 - 0 1 - 1 0 - 1 1 - .5 .5 +``` + 0 0 + 0 1 + 1 0 + 1 1 + .5 .5 +``` Strictly speaking, you have to provide a **set** of points. If there are duplicates in the list, there is no guarantee on the one to be shown (in -addition their labels will overlap) in the resulting colored Voronoi diagram. +addition their labels will overlap) in the resulting colored [Voronoi +diagram](https://en.wikipedia.org/wiki/Voronoi_diagram). ### Caution This program might have been a lot shorter, but nearly impractical even for medium sized datasets. On the other hand it could have been a lot faster, but -hard to qualify under the IOCCC size limit. So guess what I did a compromise +hard to qualify under the IOCCC size limit. So guess what I did? A compromise favoring innermost obfuscation, sacrificing sometimes speed and other tedious factors. @@ -78,61 +99,66 @@ Therefore this entry is limited to > ![floor\bigg(\frac{10^6}{4\times(sizeof(double)+1)}-1\bigg)](eqn.png) -points and won't even be suitable for more than a few thousand : although -generated files do pass [W3C SVG Validator], and are highly compressible, -they are not as scalable as their name suggests… For serious applications -about Voronoi diagrams, see [Qhull], [CGAL] and the like : but you may -still encounter large output volumes (and have to handle some sort of clipping -in order to represent properly infinite regions of the diagram in SVG). - - [W3C SVG Validator]: http://jiggles.w3.org/svgvalidator/ - [Qhull]: http://www.qhull.org/ - [CGAL]: http://www.cgal.org/ +points and won't even be suitable for more than a few thousand; although +generated files did pass the [W3C SVG +Validator](https://validator.w3.org/#validate_by_upload+with_options), and are +highly compressible, they are not as scalable as their name suggests... For +serious applications about [Voronoi +diagrams](https://en.wikipedia.org/wiki/Voronoi_diagram), see +[Qhull](http://www.qhull.org/), [CGAL](https://www.cgal.org) and the like but +you may still encounter large output volumes (and have to handle some sort of +clipping in order to represent properly infinite regions of the diagram in +[SVG](https://www.w3.org/TR/SVG11/expanded-toc.html)). Beware, compilation may report warnings about precision loss, linting may be a disaster, but the code should remain portable, and the output accurate enough for most devices (including many inkjet printers). If you ever miss precision -on a particular dataset or peripheral, you may want to dive in and let U be +on a particular dataset or peripheral, you may want to dive in and let `U` be the next power of `__LINE__`. -Note : bad inputs will be sanctioned by the production of the 42nd Mersenne -prime (ie. 2^25964951 -1), memory will be kept. +NOTE: bad inputs will be sanctioned by the production of the 42nd Mersenne +prime (ie. 2^25964951 -1); memory will be kept. ### Why I think this code is Obfuscated ? -I'm quite divided on the subject because I wrote : +I'm quite divided on the subject because I wrote: - * clear SVG key words but complicated output statements - * no nested loops but loads of function calls - * easy recursion but no clear data struture - * easy maths but no use of math.h - * a single if +* Clear [SVG](https://www.w3.org/TR/SVG11/expanded-toc.html) keywords but +complicated output statements. +* No nested loops but loads of function calls. +* Easy recursion but no clear data structure. +* Easy maths but no use of `math.h`. +* A single `if`. Be sure to check the antepenultimate line of code. ### Missing Features -**Color control** -> Cell colors are chosen randomly (with a questionable rejection scheme). It +#### Color control + +Cell colors are chosen randomly (with a questionable rejection scheme). It might have been useful to input them along with sites coordinates, turning the application into a puzzling graphics engine. -**Site labelling** -> The points are implicitly numbered in the order they were entered +#### Site labelling + +The points are implicitly numbered in the order they were entered (starting at one). This can be overridden however, via a simple XSL transformation. -**Site radius** -> The site radius is hardwired in the code, I still wonder why I did not +#### Site radius + +The site radius is hardwired in the code, I still wonder why I did not design it as a function of the underlying cell's area (which can be averaged for free) or at least a command line parameter. Same with the char set, the -viewport and potentially every SVG property. +viewport and potentially every +[SVG](https://www.w3.org/TR/SVG11/expanded-toc.html) property. ### See Also - [Voronoi at Wikipedia](http://en.wikipedia.org/wiki/Voronoi_diagram), - [An Excerpt from The Algorithm Design Manual](http://www2.toki.or.id/book/AlgDesignManual/BOOK/BOOK4/NODE187.HTM), - [Voronoi and Art](http://www.snibbe.com/scott/bf) +- [Voronoi at Wikipedia](http://en.wikipedia.org/wiki/Voronoi_diagram), +- [An Excerpt from The Algorithm Design Manual](http://www2.toki.or.id/book/AlgDesignManual/BOOK/BOOK4/NODE187.HTM), +- [Voronoi and Art](http://www.snibbe.com/scott/bf) ### Example Output diff --git a/2005/chia/README.md b/2005/chia/README.md index b4adfebfe..de6bf8b1c 100644 --- a/2005/chia/README.md +++ b/2005/chia/README.md @@ -1,8 +1,8 @@ # Most ambiguous language - V. Chia - Singapore - bi@mncw.tk +V. Chia +Singapore + ## To build: @@ -32,29 +32,38 @@ for "stringification". ## Author's remarks: Two things inspired this entry. First, there were the C programs which were -`#define`'d to look like Pascal or Visual Basic: the /bin/sh code from V7 Unix -(which reportedly was the motivation behind this contest!), the VAL Linker by -David Troendle, the 2000/primenum entry, ... Looking at these programs, I -thought, "hmm... if it's possible to make C code look like some weird cross -between Pascal, VB, and COBOL, then how about making C code look like some -other language?" +`#define`'d to look like [Pascal][] or [Visual Basic][]: the +[/bin/sh](https://en.wikipedia.org/wiki/Bourne_shell) code from [V7 +Unix](https://en.wikipedia.org/wiki/Version_7_Unix) (which reportedly was the +motivation behind this contest!), the [VAL +Linker](http://dunfield.classiccmp.org/dos/val_src.zip) by David Troendle, the +[2000/primenum](/2000/primenum/primenum.c) IOCCC entry, ... Looking at these +programs, I thought, "hmm... if it's possible to make C code look like some +weird cross between Pascal, VB, and COBOL, then how about making C code look +like some other language?" -As chance would have it, I was writing some Java code at that time, and one of -my net.friends was also working on someone else's Java code. We both hated +As chance would have it, I was writing some [Java][] code at that time, and one of +my net friends was also working on someone else's Java code. We both hated Java; indeed, I hated Java so much that I was tired of hating it. Then I remembered my earlier idea: "Of course! Why not write C code that looks like Java? And poke fun at Java while I'm at it? All ye behold, as I turn anger into action! PH34R MII!!!!!!!" And so, this entry was born. :-) Besides carrying a revolutionary message in the comments, this entry also -draws a spiffy little Koch snowflake fractal on the screen, with the help of -ANSI escape sequences. +draws a spiffy little [Koch snowflake +fractal](https://en.wikipedia.org/wiki/Koch_snowflake) on the screen, with the help of +[ANSI escape sequences](https://en.wikipedia.org/wiki/ANSI_escape_code). The code requires a preprocessor that can stomach all kinds of nonsense that -are passed as parameters to macros for stringification. GNU cpp handles such +are passed as parameters to macros for stringification. GNU +[cpp](https://en.wikipedia.org/wiki/C_preprocessor) handles such things just fine, but certain broken preprocessors may decide to freak out when they see macro parameters that don't look like C tokens. +[Pascal]: https://en.wikipedia.org/wiki/Pascal_(programming_language) +[Visual Basic]: https://en.wikipedia.org/wiki/Visual_Basic_(classic) +[Java]: https://en.wikipedia.org/wiki/Java_(programming_language) + ## Copyright and CC BY-SA 4.0 License: This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved. diff --git a/2005/giljade/.gitignore b/2005/giljade/.gitignore index 97ec27114..af14f096f 100644 --- a/2005/giljade/.gitignore +++ b/2005/giljade/.gitignore @@ -1 +1,4 @@ giljade +giljade.alt +out +c.c diff --git a/2005/giljade/Makefile b/2005/giljade/Makefile index a9ed5f619..7557b2753 100644 --- a/2005/giljade/Makefile +++ b/2005/giljade/Makefile @@ -42,7 +42,8 @@ CSILENCE= -Wno-bitwise-conditional-parentheses -Wno-bitwise-op-parentheses \ -Wno-builtin-requires-header -Wno-empty-body -Wno-error \ -Wno-implicit-function-declaration -Wno-extra-semi -Wno-implicit-int \ -Wno-logical-op-parentheses -Wno-return-type -Wno-shift-op-parentheses \ - -Wno-unused-value -Wno-incompatible-pointer-types -Wno-int-conversion + -Wno-unused-value -Wno-incompatible-pointer-types -Wno-int-conversion \ + -Wno-parentheses -Wno-misleading-indentation # Common C compiler warning flags # @@ -57,7 +58,7 @@ CSTD= -std=gnu99 # Some entries require 32-bitness: ARCH= -m32 # Some entries require 64-bitness: ARCH= -m64 # -ARCH= -m32 +ARCH= # Defines that are needed to compile # @@ -65,7 +66,7 @@ CDEFINE= # Include files that are needed to compile # -CINCLUDE= -include stdio.h +CINCLUDE= -include stdio.h -include string.h -include unistd.h -include stdlib.h # Optimization # @@ -89,7 +90,7 @@ ifeq ($(CC),clang) # CSILENCE+= -Wno-comma -Wno-format-nonliteral -Wno-missing-prototypes \ -Wno-missing-variable-declarations -Wno-poison-system-directories \ - -Wno-strict-prototypes + -Wno-strict-prototypes -Wno-parentheses -Wno-misleading-indentation # CWARN+= -Weverything # @@ -117,8 +118,8 @@ OBJ= ${PROG}.o DATA= TARGET= ${PROG} # -ALT_OBJ= -ALT_TARGET= +ALT_OBJ= ${PROG}.alt.o +ALT_TARGET= ${PROG}.alt ################# @@ -133,7 +134,6 @@ all: data ${TARGET} supernova deep_magic magic charon pluto ${PROG}: ${PROG}.c - @echo "NOTE: this entry requires 32-bit architecture in order to run properly" ${CC} ${CFLAGS} $< -o $@ ${LIBS} # alternative executable @@ -141,6 +141,9 @@ ${PROG}: ${PROG}.c alt: data ${ALT_TARGET} @${TRUE} +${PROG}.alt: ${PROG}.alt.c + ${CC} ${CFLAGS} $< -o $@ ${LIBS} + # data files # data: ${DATA} diff --git a/2005/giljade/README.md b/2005/giljade/README.md index c53a4b1b9..c3dbe39fc 100644 --- a/2005/giljade/README.md +++ b/2005/giljade/README.md @@ -1,10 +1,8 @@ # Best 2D puzzle -Gil Dogon -1 HaBeer Alley -Jerusalem -Israel -gil_jade@netvision.net.il +Gil Dogon +Israel + ## To build: @@ -12,29 +10,37 @@ gil_jade@netvision.net.il make ``` -[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) discovered that there -are two things that are needed in order to get this to work in modern systems. -First it needs 32-bit architecture so the Makefile now has `-m32`. It appears -it's because of the size of ints being different which affects the bitwise -operations though this is just a hunch. Second is the optimiser cannot be -enabled for this to work. Both changes made and it works. This does prove a -problem for macOS as it no longer easily allows for compiling with 32-bit -possibly even if you have the Intel chip (it certainly does not work with arm64 -macOS). It might be possible to get the entry to work with 64-bit by changing -the int size but this is currently unknown. Thank you Cody for your help in -getting this to work! - - ## To run: ```sh ./giljade ``` +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed this for modern +systems. The problem that was showing up is that with either optimising or +anything but 32-bit was used it would not work. The optimising cannot be used +still but it now works with both 32-bit and 64-bit. The problem was the size of +`int` and `long` being different now. Instead of `long *E` it is now `int *E`. +This solves the problem for both 32-bit and 64-bit as long as optimising is +disabled. Tested under linux (32-bit, 64-bit) and macOS (arm64). Thank you Cody +for your assistance! + +NOTE: the self-test feature no longer works due to the fix for clang (which +requires the first arg of `main()` to be an `int` and the second arg to be `char +**`). Believe it having more than two spaces in the code, except where the +original code has them, appears to be part of the problem but it's not the full +story. If you have a compiler that doesn't have this deficiency (e.g. gcc) you +can use the alternate code described below. + +### INABIAF - it's not a bug it's a feature! :-) + +If the program source file is not lying in the same directory this program will +very likely crash or do something strange. + ## Try: ```sh -giljade > out +./giljade > out ``` Open an xterm with 78 lines. @@ -44,13 +50,28 @@ vi out Press ^F (control F) repeatedly. +### Alternate code: + +Thanks to the fix for `clang` the self-test feature (of the output, see the +author's remarks) does not work. If however you have gcc which does not have the +defect that clang has with requirements in `main()`s args you can still use it +via the alternate code. To compile: + + +```sh +make alt +``` + +Use `giljade.alt` as you would `giljade`. + + ## Judges' remarks: This entry takes editorial in how it deals with its output. After using vi to look at the source, use vi to look at its output. We especially recommend it on a 78 column xterm while leaning on Control-F. -Do you really understand expressions, then understand this: +If you really understand expressions, then understand this: ```c s=s^(b=s&s-1^s) @@ -65,8 +86,8 @@ s=s^(b=s&s-1^s) Just run the executable with no command line args and look at the output. In order to properly enjoy it you will need two good old programs: xterm and vi. Do the following: open an xterm with precisely 78 lines, and use the tiny font -size for best results. Then vi (vim will also do) the output. Type ^F's and -enjoy the show ... +size for best results. Then vi (vim will also do) the output. Type `^F` +repeatedly or hold it down and enjoy the show ... The program solves (very very fast) a sliding block puzzle. There are many variants of such puzzles which are usually made from wood or plastic pieces. @@ -74,9 +95,9 @@ The start position can be recognized by looking at the program itself. The goal is to move the big piece (2 by 2) to the center top, which takes 179 steps in the shortest move sequence. -Notice: the step count used by the program is longer than the traditional step -count for such puzzles, as normally if the same piece is moved twice in a row -it is counted as only one step, but here it is counted as two. +Notice that the step count used by the program is longer than the traditional +step count for such puzzles, as normally if the same piece is moved twice in a +row it is counted as only one step, but here it is counted as two. The printout of the solution however is in a rather unorthodox form, as can be easily discerned. As you have probably suspected each of the steps in the @@ -88,10 +109,10 @@ layouts. It is self-improving, in that the programs it prints have three advantages over the original: 1. Their layout is more precise (Notice the annoying \ at the 10'th line of -the original program which is actually a 'layout bug' +the original program which is actually a 'layout bug'). 2. Their binary output does not rely on the source file being in the same -directory, and will not dump core like the original if it doesn't. :) +directory, and will not dump core if it doesn't (like the original does). :) 3. They have much more comments (Not very helpful ones though). @@ -100,56 +121,55 @@ places, and checking that indeed the output is composed of 180 legal C programs by hand can be quite tedious, hence the program also include a self- test mode. Just run it with the output file as command line argument. It will then try to compile each of the programs (printing the line number where the -program starts) It will stop where any compilation fails and the culprit -program would be in the file 'c.c'. The exit code of the self-test will be +program starts). It will stop where any compilation fails and the culprit +program would be in the file `c.c`. The exit code of the self-test will be non-zero in that case. In case this entry wins, I do hope nobody by the name of 'c' also wins this year otherwise that part of the program would have to be changed! Notice that the self-test does not try to run the result of the compilations -but this can easily be done. try it and diff the output of any of the 180 +but this can easily be done. Try it and diff the output of any of the 180 results with the original output. Of course all 180 programs also include the self-test mode. ### Why I think this program is obfuscated. - * Because its says so, and twice is better than once! - * All the usual suspects i.e. ?: && || , used to compress code length in the -noble tradition of this contest, meaningless one character variable names, -etc... - * The board representation is efficiently compressed hence obfuscated, and +* Because it says so, and twice is better than once! +* All the usual suspects i.e. `?:`, `&&`, `||`, `,` used to compress code +length in the noble tradition of this contest, meaningless one character +variable names, etc... +* The board representation is efficiently compressed hence obfuscated, and the algorithm that is used to generate possible moves is extremely efficient. -In fact it can compute several moves in parallel on one processor! Moreover -Only the most efficient bitwise logical operations, shift,and subtraction by -one is used. No inefficient conditional tests and jumps are needed in that -part of the program. - - * The single expression I'm most proud of, and would have submitted to the + In fact it can compute several moves in parallel on one processor! Moreover + Only the most efficient bitwise logical operations, shift,and subtraction by + one is used. No inefficient conditional tests and jumps are needed in that + part of the program. +* The single expression I'm most proud of, and would have submitted to the category of 'best obfuscated short expression' if there was one is: s=s^(b=s&s-1^s) -Can you figure out what it does (very efficiently) and how it fits in the -scheme of things? + Can you figure out what it does (very efficiently) and how it fits in the + scheme of things? - * IMHO the program is easier to understand before running cpp on it. It is -also shorter that way to be sure. - * It even takes care to obfuscate the comments in the output programs. - * Having the output programs a bit different than the original is more +* IMHO the program is easier to understand before running cpp on it. It is also +shorter that way to be sure. +* It even takes care to obfuscate the comments in the output programs. +* Having the output programs a bit different than the original is more interesting. - * I have written an earlier version of the program about half a year ago and -when returning to it now I had to sweat quite a lot to understand the f***ing +* I have written an earlier version of the program about half a year ago and +when returning to it now I had to sweat quite a lot to understand the f\*\*\*ing mess I've made. ### Known Bugs/problems/warnings/portability issues -Some CPPs issue a warning about empty macro parameters. +Some `CPP`s issue a warning about empty macro parameters. --pedantic informs me that 'ISO C' does not allow extra ; outside of a -function, and I to this I say ISO what ??? +`-pedantic` informs me that 'ISO C' does not allow extra ; outside of a +function, and to this I say to ISO what ??? --Wall of course will suggest adding a lot of parenthesis, function prototypes, +`-Wall` of course will suggest adding a lot of parenthesis, function prototypes, and remove some unnecessary expressions, and to this I say: if I listen to you where is my freedom to obfuscate in style? @@ -157,26 +177,26 @@ As mentioned earlier if you try to run the original program without its source nearby it will dump core. The program relies heavily on the ASCII coding system (have I seen this -comment before ?). It also implicitly assumes that sizeof(int) = sizeof(FILE -*). On systems when that is not the case expect a core dump... +comment before ?). It also implicitly assumes that `sizeof(int) = sizeof(FILE +*)`. On systems when that is not the case expect a core dump... ### Challenges -What use are the ;; for ? +What use are the `;;` for ? -Why do I use 126& in the program? (except for the rather obvious fact that it +Why do I use `126&` in the program? (except for the rather obvious fact that it serves as comment obfuscater). -Why not write s^= instead of s=s^ In the expression I'm most proud of ? +Why not write `s^=` instead of `s=s^` In the expression I'm most proud of ? -What is 40-(h&62) doing ? +What is `40-(h&62)` doing ? Use the program to solve for a different starting position. It is not that difficult. Notice however that if there are more than two empty spaces the outputs would not compile as the layout would not be sufficient to contain the program. -Use the program to solve for board size different than 4*5. Thats a bit more +Use the program to solve for board size different than `4*5`. That's a bit more tricky. ### Hint for the challenges diff --git a/2005/giljade/giljade.alt.c b/2005/giljade/giljade.alt.c new file mode 100644 index 000000000..11a8398d2 --- /dev/null +++ b/2005/giljade/giljade.alt.c @@ -0,0 +1,49 @@ + #define/**/F/***/for/*A*/ + #define/***/H()f=*E<<4|*\ + E,f=~(f|f<<1|E[3]|E[1]|E\ + [1]<<4|E[2]|E[(2)]<<(1)); + #define/***/I(x,d)F(;s;C\ + ()){s=s^(b=s&s-1^s);F(N[\ + 4]=q=0;q<4;q++)N[q]=E[q]\ + ;N[5]=E-B;N[d]^=+b^(b)x;} + #define/**/o(p,t,i,m,a,l\ +\ +)u=(f&p)i(m) ;s=u&E[3];I(t(m),3)s=(u)a &E[l];I(t(m\ +),l)u=u>>5-m &u;s=u&E[3-l];I(t(m),3-l) s=(u)a&*E;I\ +(t(m),(0));; /*echo/Line/%d;sed/-n/-e/ %d,%dp/%s>*/ +/*c.c;cc/c.c /-c*/;;char*A=0,*_,*R,*Q, D[9999],*r,l +[9999],T=42, M,V=32;long*E,k[9999],B[1 <<+21],*N=B+ +1234567,q=0, h=3,j=2,O,b,f,u,s,c,a,t,e ,d;C(){F(h=N +[3];(B[h]&&+ memcmp(N,B+B[h],16));h=B[ h]+4);B[h]|| +(B[h]=N-B,N= N+6);}main(char*U,int*w[] ){;;F(_=A=D+ +6666,A[fread (A,1,3333,fopen(__FILE__, "r"))]=0;*++ +_;h||(*_=V)) +*_-59|_[1]-* _||(h&&(*_=+ 35),h---2||(_[9]=V));;F(_ +=A;*_;_++)10 -*_&&*_-V&&( *_-92)&&(k[q]=isalnum(l[q +]=*_),q++);M =47;*(E=N-6) =64;E[1]=289;E[2]=270336; +F(E[3]=32782 ;E>,4,>>4, +1)o(+489335, >>,<<,1,,2)o (978670,<<,>>,1,>>1,2)o(+ +65535,>>,<<, 4,,1)if(8192 &*E){F(N=B;E>B;E=B+E[5])* +N++=E-B;F(;N >B;){h=*(E=B +*--N);H()s=~(E[1]|h|h<<1 +);u=~(E[2]|h |h<<4);r=l;_ =D;d=1;a=2;O=8;F(q=74;q;q +--){F(b=0;b< 72;b++){h=+1 <<(q-1)/14*4+(b-1)/18;j=b + ?(!(b%18)&&u &h)|h&f|(!(q%14)&&s&h)?1: +0:2;if(O<3)O ?j?j-1&&(O-2 &&d--,*R=34,O=2):(*_++=O- +2?l[d]?l[d++ ]:(d=t,O=e=3 ,34):(O=1,34)):j||(*_++=d +j &&(sprintf(l +,r+1,j,j,O=j +75,w[1]),j= O,!system(l) ););exit(j<+ +13499);}t=d+ 9;_[-1]=l[++ d];}a-1|+j-2 ||(R-Q<3?(*( +Q++R;) ;}}};O-b-f-u -s-c-a-t-e;} diff --git a/2005/giljade/giljade.c b/2005/giljade/giljade.c index 9649e826d..bc1bf6040 100644 --- a/2005/giljade/giljade.c +++ b/2005/giljade/giljade.c @@ -12,12 +12,12 @@ ),l)u=u>>5-m &u;s=u&E[3-l];I(t(m),3-l) s=(u)a&*E;I\ (t(m),(0));; /*echo/Line/%d;sed/-n/-e/ %d,%dp/%s>*/ /*c.c;cc/c.c /-c*/;;char*A=0,*_,*R,*Q, D[9999],*r,l -[9999],T=42, M,V=32;long*E,k[9999],B[1 <<+21],*N=B+ +[9999],T=42, M,V=32;int*E,k[9999],B[1 <<+21],*N=B+ 1234567,q=0, h=3,j=2,O,b,f,u,s,c,a,t,e ,d;C(){F(h=N [3];(B[h]&&+ memcmp(N,B+B[h],16));h=B[ h]+4);B[h]|| (B[h]=N-B,N= N+6);}int main(int Ua,char**wa){char*U =Ua;int**w= wa;;F(_=A=D+6666,A[fread(A,1,3333,fopen -(__FILE__, "r"))]=0;*++ _;h||(*_=V)) +(__FILE__, "r"))]=0;*++ _;h||(*_=V)) *_-59|_[1]-* _||(h&&(*_=+ 35),h---2||(_[9]=V));;F(_ =A;*_;_++)10 -*_&&*_-V&&( *_-92)&&(k[q]=isalnum(l[q ]=*_),q++);M =47;*(E=N-6) =64;E[1]=289;E[2]=270336; diff --git a/2005/jetro/README.md b/2005/jetro/README.md index fec6ce488..085360b1c 100644 --- a/2005/jetro/README.md +++ b/2005/jetro/README.md @@ -1,9 +1,8 @@ # Most sonorous output - Jetro Lauha - Talonpojantie 5A9, - 00790 Helsinki - +Jetro Lauha +Finland + ## To build: @@ -13,60 +12,8 @@ This entry requires SDL to be installed. make ``` -### To install SDL and SDL2: - -#### macOS users - -If you have not aleady do so, install Homebrew. See the following for information: - - https://brew.sh - -Then to install SDL and SDL2, execute the following command: - -```sh -brew install sdl2 sdl12-compat -eval "$(/opt/homebrew/bin/brew shellenv)" -``` - -#### Linux users: - -To install SDL and SDL2, execute the following command as root: - -```sh -dnf install SDL2 SDL2-devel sdl12-compat sdl12-compat-devel -``` - -Use make as follows: - -```sh -make ... SDL2_INCLUDE_ROOT=/usr -``` - -or set the following environment variable: - -```sh -export SDL2_INCLUDE_ROOT=/usr -``` - -#### Debian users - -To install SDL and SDL2, execute the following command as root: - -```sh -apt install libsdl1.2debian libsdl1.2-dev libsdl2-dev -``` - -Use make as follows: - -```sh -make ... SDL2_INCLUDE_ROOT=/usr -``` - -or set the following environment variable: - -```sh -export SDL2_INCLUDE_ROOT=/usr -``` +See the [faq](/faq.md) for information on how to install it if you haven't +already. ## To run: diff --git a/2005/klausler/Makefile b/2005/klausler/Makefile index c0d0a31e1..196456216 100644 --- a/2005/klausler/Makefile +++ b/2005/klausler/Makefile @@ -130,7 +130,7 @@ all: data ${TARGET} .PHONY: all alt data everything clean clobber install \ love haste waste maker easter_egg sandwich \ - supernova deep_magic magic charon pluto + supernova deep_magic magic charon pluto dict.h ${PROG}: dict.h ${PROG}.c ${CC} ${CFLAGS} ${PROG}.c -o $@ ${LIBS} diff --git a/2005/klausler/README.md b/2005/klausler/README.md index 0ce515d5f..eaddf111a 100644 --- a/2005/klausler/README.md +++ b/2005/klausler/README.md @@ -1,11 +1,8 @@ # Abuse of the rules - Peter Klausler - Cray Inc. - 2802 W 40th St - Minneapolis MN 55410 - USA - pmk@cray.com +Peter Klausler +US + ## To build: @@ -16,7 +13,7 @@ make ## To run: ```sh -./klausler arg1 agr2 | head +./klausler arg1 arg2 | head ``` ## Try: @@ -37,18 +34,19 @@ Rules might have to be changed! ## Author's remarks: -A useful tool to help one appear extra smart and witty when IRCing, or even -just highly annoying. +A useful tool to help one appear extra smart and witty when +[IRC](https://en.wikipedia.org/wiki/Internet_Relay_Chat)ing, or even +just be highly annoying. Finds best anagrams for word or phrase given as program arguments. Use only lower-case letters in these arguments. Output is sorted firstly in ascending order of word count (fewer words are better) and secondly in descending order -of word length. Pipe the output into more(1)/less(1)/head(1) and you're likely +of word length. Pipe the output into `more(1)`/`less(1)`/`head(1)` and you're likely to find the most amusing possibilities in the first few screenfuls of output. -For example, "ana fawlty towers | more" quickly prints "waterfowl sty". The +For example, `./klausler fawlty towers | more` quickly prints "waterfowl sty". The fewer obscure short words in your system's dictionary, the better the quality -of the output; indeed, all one-letter words apart from "a", "i", and "s" (for -plurals) are ignored when the dictionary is constructed by build.sh. +of the output; indeed, all one-letter words apart from `a`, `i`, and `s` (for +plurals) are ignored when the dictionary is constructed by `make dict.h`. Some history and explanation: When I noticed the call for entries in this year's IOCCC, I submitted two of them. I worked on the first one very hard to @@ -62,7 +60,7 @@ I'm embarrassed to admit that I don't even know which specific rule this entry has abused. It's just yet another anagram generator and it was written very late one night. And now I honestly do not know how it works, so please don't ask. Upon reviewing the program after its unexpected honor, I guess that it's -remarkable only for its complete lack of macros, sneaky naming, main() +remarkable only for its complete lack of macros, sneaky naming, `main()` recursion, or other tricks. Enjoy! ## Copyright and CC BY-SA 4.0 License: diff --git a/2005/mikeash/README.md b/2005/mikeash/README.md index 19af62162..df9c3fb13 100644 --- a/2005/mikeash/README.md +++ b/2005/mikeash/README.md @@ -1,8 +1,9 @@ # Best use of parenthesis - Michael Ash - USA - mike@mikeash.com +Michael Ash +US +mike@mikeash.com + ## To build: @@ -23,121 +24,130 @@ make ./mikeash < mikeash.c | diff - mikeash.c ``` +NOTE: the author stated that they tested this under i386 machines but this works +under 64-bit (x86_64, arm64) machines too. + ## Judges' remarks: -Having problems speaking code? Do you LISP? Parenthetically +Having problems speaking code? Do you [LISP][]? Parenthetically speaking, this entry takes advantage of C99 features, while speaking parenthetically. Best of all, it self-reproduces! John McCarthy might not of imagined it quite like this! :-) +[LISP]: https://en.wikipedia.org/wiki/Lisp_(programming_language) + ## Author's remarks: This program is a self-reproducing program, which is on the IOCCC's list of discouraged program types. Worse, it's a self-reproducing program -written in Common Lisp. What's this doing as an entry to the IOCCC? +written in [Common Lisp](https://en.wikipedia.org/wiki/Common_Lisp). What's this +doing as an entry to the IOCCC? -Start over; this program, when compiled with a C99 compiler, is an -interpreter for an extremely limited and highly broken subset of Common -Lisp. +Start over: this program, when compiled with a C99 compiler, is an +interpreter for an extremely limited and highly broken subset of [Common +Lisp](https://en.wikipedia.org/wiki/Common_Lisp). -It requires C99 because of C99's ability to declare variables in the +It requires C99 because of `C99`'s ability to declare variables in the initializer of a for loop. Unfortunately, C99 mode typically warns about -implicitly declared functions, and preprocessor directives prevent the -program from being valid Common Lisp. As a result, several warnings will -be printed about implicit declarations of functions. There are also -warnings about unknown escape sequences in the constant string, due to -different string escape semantics in C and Lisp, and some implicit -integer-to-pointer conversions due to the implicitly-declared functions. +implicitly declared functions, and preprocessor directives prevent the program +from being valid [Common Lisp](https://en.wikipedia.org/wiki/Common_Lisp). As a +result, several warnings will be printed about implicit declarations of +functions. There are also warnings about unknown escape sequences in the +constant string, due to different string escape semantics in C and Lisp, and +some implicit integer-to-pointer conversions due to the implicitly-declared +functions. Try: ```sh -echo '(format t "~s" (+ 2 2 ))' | ./lispob +echo '(format t "~s" (+ 2 2 ))' | ./mikeash ``` -You should see '4"' echoed on your command prompt. The " after the 4 and +You should see `4"` echoed on your command prompt. The `"` after the 4 and the lack of a newline are due to the somewhat broken implementation of the format function. More sophisticated arithmetic expressions may be used: ```sh -echo '(format t "~s" (* (+ 2 2 ) (- 5 (/ 9 3 ))))' | ./lispob +echo '(format t "~s" (* (+ 2 2 ) (- 5 (/ 9 3 ))))' | ./mikeash ``` -This evaluates the expression (2+2) * (5 - 9/3) giving the correct +This evaluates the expression `(2+2) * (5 - 9/3)` giving the correct result, 8. Note that due to the highly ad-hoc nature of the tokenizer, -the spaces before the closing paretheses are mandatory. +the spaces before the closing parentheses are mandatory. The program can also be run in an interactive mode, by simply executing -./lispob and then typing lisp expressions, but this is difficult due to the +`./mikeash` and then typing lisp expressions, but this is difficult due to the lack of proper editing facilities and the total lack of error recovery in the interpreter. Typos will most likely crash the program. -Aside from being required to put spaces between tokens and closing -parentheses, there are other limitations on the dialect of Common Lisp -that this program understands: +Aside from being required to put spaces between tokens and closing parentheses, +there are other limitations on the dialect of [Common +Lisp](https://en.wikipedia.org/wiki/Common_Lisp) that this program understands: -* The only built-in functions are defvar, format, substitute, char-upcase, -+, -, *, and /. +* The only built-in functions are `defvar`, `format`, `substitute`, +`char-upcase`, `+`, `-`, `*`, and `/`. -* Only one variable is available. This variable is called 'q', although any -symbol name starting with the letter 'q' will be mapped to this variable. +* Only one variable is available. This variable is called `q`, although any +symbol name starting with the letter `q` will be mapped to this variable. * Only the first letter of a function name is significant. For example, -format, f, farm, and various other words starting with 'f' will all map to the -format function. +`format`, `f`, `farm`, and various other words starting with `f` will all map to +the `format` function. -* The defvar function completely ignores its first parameter. It will always -store the result of evaluating its second parameter in 'q'. Unlike in Common -Lisp, multiple invocations of defvar on the same variable will overwrite old -values. +* The `defvar` function completely ignores its first parameter. It will always +store the result of evaluating its second parameter in `q`. Unlike in [Common +Lisp](https://en.wikipedia.org/wiki/Common_Lisp), multiple invocations of +`defvar` on the same variable will overwrite old values. -* Character constants are limited to #\Newline and single-character -constants such as #\x. +* Character constants are limited to `#\Newline` and single-character +constants such as `#\x`. -* The char-upcase function will give strange results if passed something +* The `char-upcase` function will give strange results if passed something other than a lowercase character. * The format function takes exactly three parameters. The first parameter is ignored; output always goes to stdout. The second parameter must have exactly -one ~s format specifier in it, and no other format specifiers are permitted. +one `~s` format specifier in it, and no other format specifiers are permitted. * The arithmetic functions take exactly two parameters. -* All tokens must be separated from a following ) by whitespace. +* All tokens must be separated from a following `)` by whitespace. -* A lot of other things. Notably, the language which this program interprets -is nowhere near Turing-complete. +* A lot of other things. Notably, the language which this program interprets is +nowhere near +[Turing-complete](https://en.wikipedia.org/wiki/Turing_completeness). -Basically, the lisp interpreter is good for some basic math operations, and +Basically, the [LISP][] interpreter is good for some basic math operations, and for running itself. To do the latter, try this: ```sh -./lispob < lispob.c > lispob2.c -diff lispob.c lispob2.c +./mikeash < mikeash.c > mikeash2.c +diff mikeash.c mikeash2.c ``` -The program can also be run from an implementation of common lisp. To do -this, run the common lisp compiler and then type the following command: +The program can also be run from an implementation of [common +lisp](https://en.wikipedia.org/wiki/Common_Lisp). To do +this, run the [common lisp compiler and then type the following command: ``` -(load "lispob.c") +(load "mikeash.c") ``` -The source code of lispob.c will be printed. +The source code of [mikeash.c](mikeash.c) will be printed. -Lispob is obfuscated in several ways. First, it's actually two programs +`Lispob` is obfuscated in several ways. First, it's actually two programs in one, which actually share a small amount of code. Running a C code -beautifier will destroy the lisp program contained within. Second and +beautifier will destroy the [LISP][] program contained within. Second and more importantly, it is very badly written, which will presumably confuse people who are used to looking at well-implemented interpreters. -The program comes in at just under 2k of significant characters. -However, this size is exaggerated, because it contains a complete copy -of itself for the self-reproducing lisp program, making it twice the -size. This doubling effect made it something of a challenge to fit -inside the IOCCC's size limit. +The program comes in at just under 2k of significant characters. However, this +size is exaggerated, because it contains a complete copy of itself for the +self-reproducing [LISP](https://en.wikipedia.org/wiki/Turing_completeness) +program, making it twice the size. This doubling effect made it something of a +challenge to fit inside the IOCCC's size limit. This code should be highly portable. It was tested under Mac OS X and Linux on i386, but it should run elsewhere. It requires ASCII due to diff --git a/2005/mynx/.gitignore b/2005/mynx/.gitignore index 760b192f2..11a543853 100644 --- a/2005/mynx/.gitignore +++ b/2005/mynx/.gitignore @@ -1 +1,4 @@ mynx +mynx.alt +source/config.* +source/makefile diff --git a/2005/mynx/Makefile b/2005/mynx/Makefile index 8531dc060..72f898a29 100644 --- a/2005/mynx/Makefile +++ b/2005/mynx/Makefile @@ -114,8 +114,8 @@ OBJ= ${PROG}.o DATA= source/configure source/configure.in entities.txt source/makefile.in TARGET= ${PROG} # -ALT_OBJ= -ALT_TARGET= +ALT_OBJ= ${PROG}.alt.o +ALT_TARGET= ${PROG}.alt ################# diff --git a/2005/mynx/README.md b/2005/mynx/README.md index f85715c43..d7a2d2791 100644 --- a/2005/mynx/README.md +++ b/2005/mynx/README.md @@ -1,11 +1,8 @@ # Best use of the www - Anthony Howe - Snert - 42 av. Isola Bella - 06400 Cannes, - France - achowe@snert.com +Anthony Howe + + ## To build: @@ -13,6 +10,11 @@ make ``` +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed this so that the +[configure](source/configure) script (which is not needed but part of the entry) +would work with compilers that have by default `-Werror` like clang in macOS. +Thank you Cody! + ## To run: ```sh @@ -22,6 +24,8 @@ make You can specify a port by appending to the domain `:port`. See notes below on the issue of https. + + ## Try: ```sh @@ -30,28 +34,52 @@ the issue of https. [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) pointed out that this -will not work for https initially for two reasons. First it scanned for http://. -Cody changed it to scan for both http:// and https:// but the problem is a -secure connection needs to be set up before http commands can be sent. One would -also have to specify a port in the URL. Fortunately or unfortunately many more -websites use https nowadays so this entry will not work as well as it used to. -If one were to try and connect to `http://www.ioccc.org` with this entry they'll -just get a 301 error. Perhaps someone can come up with a pipeline that will make -this work with the change made. Otherwise just enjoy it for what it was. +will not work for https initially for two reasons. For a starting point see the +alternate code section below. + +### Alternate code: + +As noted this will not work for https. This is because it does not scan for +https but also a secure connection needs to be set up before http commands can +be sent. One would also have to specify a port in the URL. Fortunately or +unfortunately many more websites use https nowadays so this entry will not work +as well as it used to. If one were to try and connect to `http://www.ioccc.org` +with this entry they'll just get a 301 error. + +In case someone can come up with a clever pipeline or some other hack or +workaround (perhaps [stunnel](https://www.stunnel.org)), Cody added the alt code +which does scan for https. Futile, maybe, in which case just enjoy it for what +it was. To compile: -## Judges' remarks +```sh +make alt +``` -This little mynx will give any Fiery Fox a run for its money. A nice complement -to last years winning hibachi. The judges double dare any eager -Obfuscationalists to submit the missing pieces to get a functioning LAMP stack. +Use `mynx.alt` as you would `mynx`. You'd have to specify a port at the end of +the URL like: + +```sh +./mynx.alt https://www.ioccc.org:443 +``` + +but again unless you have a clever workaround or hack to the problem, this sadly +won't work. + +## Judges' remarks: + +This little `mynx` will give any [Fiery +Fox](https://en.wikipedia.org/wiki/Firefox) a run for its money. A nice +complement to last years winning [hibachi](/2004/hibachi/src/hibachi.c). The +judges double dare any eager Obfuscationalists to submit the missing pieces to +get a functioning LAMP stack. ## Author's remarks: -I was rather impressed by last year's mini web server. So much so that +I was rather impressed by last year's mini webserver. So much so that it inspired me to try my hand at writing the client side complement. -A typical build would be command would be: +A typical build command would be: ```sh cc -omynx mynx.c @@ -69,26 +97,27 @@ all the network functions in a variety of places. So a simpler build command sequence would be: ```sh -./configure -make +cd source ; ./configure ; make ``` After which, the rest of the documentation can be read by saying: ```sh -./mynx manual.html +./mynx ../manual.html ``` Manifest: - mynx.c - makefile pre-built generic Un*x - README.TXT - manual.html - makefile.in makefile template - entities.txt ISO 8859-1 entites - configure.in configure script description - configure pre-built configure script +``` + mynx.c + makefile pre-built generic Un*x + README.TXT + manual.html + makefile.in makefile template + entities.txt ISO 8859-1 entites + configure.in configure script description + configure pre-built configure script +``` ## Copyright and CC BY-SA 4.0 License: diff --git a/2005/mynx/mynx.alt.c b/2005/mynx/mynx.alt.c new file mode 100644 index 000000000..6476d1eb0 --- /dev/null +++ b/2005/mynx/mynx.alt.c @@ -0,0 +1,224 @@ +#define I int +#define c char * +#define G fscanf(f, +#define W while( +#define k return +#define Q if( +#define Z 512 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +FILE *f; +short w[4] = { 24, 80 }; +I L, B, r, H; +c l[Z], b[Z], s[Z], S[Z][10], T[Z], h[Z]; +I +e(c s) +{ + I n = 0; + Q *s == '#') + k (I) strtol(s+1, 0, 0); + W n < Z) { + Q *S[n] && !strcmp(s, S[n]+1)) + k *S[n]; + n++; + } + k '?'; +} +void +P(I x) +{ + Q x == '\n' || w[1] - 3 < B) { + b[B] = 0; + b[B+1] = 0; + B = printf("%s", b); + B = snprintf( + b, Z, + "\n %s", + b + B + 1 + ); + r++; + } + Q b[B-1] != ' ' || !isspace(x)) { + b[B++] = isspace(x) ? ' ' : x; + Q w[1] - 3 < B) + *strrchr(b, ' ') = 0; + } +} +void +p(c t, ...) +{ + va_list x; + va_start(x, t); + vsnprintf(s, Z, t, x); + t = s; + W *t) + P(*t++); + va_end(x); +} +I +X(c s) +{ + I x; + c t = s; + long m = ftell(f); + W *t && (x = fgetc(f)) != EOF) { + Q *t == '*') + s = t++; + Q tolower(x) != *t) { + Q *s != '*') + break; + t = s; + } + t++; + } + Q *t) + fseek(f, m, SEEK_SET); + k !*t; +} +void +d(c s) +{ + Q 4 < B) + P('\n'); + P('\n'); + Q *s == 'h') + B = 1; +} +void +a(c s) +{ + *T = 0; + G + ungetc(fgetc(f), f) == '"' + ? "\"%511[^\"]" + : "'%511[^']", + T + ); + Q *s == 'a' || *s == 'f' || s[1] == 'f') { + free(l[++L]); + l[L] = strdup(T); + p(" [%d] ", L); + } + Q *s != 'a') + p("%s%s\n", T, *s == 'b' || s[1] == 'h' ? "" : "\n"); + X("*>"); +} +void *Y[] = { + "!--*-->" , 0 , + "a *href=" , a , + "ifr*src=" , a , + "fra*src=" , a , + "img*src=" , a , + "p*>" , d , + "bl*>" , d , + "br" , a , + "hr" , a , + "h*>" , d , + "/h" , a , + "/tr" , a , + "/dt" , a , + "/dd" , a , + "li*>" , d , + "*>" , 0 , + 0 , 0 +}; +I +main(I V, c *v) +{ + I x, n = 0; + c t = v[1]; + ioctl(0, TIOCGWINSZ, w); + f = fopen("entities.txt", "r"); + Q f) { + W G "%s %d", S[n]+1, &x) == 2) + *S[n++] = x; + fclose(f); + n = 0; + } + W t) { + I m = 0; + struct hostent *y; + struct sockaddr_in A; + L = 0; + B = 1; + Q (!sscanf(t, "http://%255[^/]%n", h, &n)&&!sscanf(t,"https://%255[^/]%n",h, &n) && !*h)) { + Q !(f = fopen(t, "rb"))) + k 1; + goto e; + } + Q 0 < sscanf(h, "%*[^:]%n:%d", &x, &H)) + h[x] = 0; + else + H = 80; + y = gethostbyname(h); + Q !y) + k 1; + memcpy(&A.sin_addr.s_addr, y->h_addr, y->h_length); + A.sin_port = htons( (short) H); + A.sin_family = y->h_addrtype; + f = tmpfile(); + Q !f) + k 1; + W + connect( + m = socket( + A.sin_family, SOCK_STREAM, 0 + ), (void *) &A, sizeof A + ) + || errno == EINTR + ) + ; + n = snprintf( + b, Z, + "GET %s%s HTTP/1.0\r\nHost: %s:%d\r\n\r\n", + t[n] == '/' ? "" : "/", t+n, h, H + ); + Q send(m, b, n, 0) == n) { + W 0 < (n = recv(m, b, Z, 0))) + fwrite(b, 1, n, f); + } + close(m); + rewind(f); + X("*\r\n\r\n"); +e: + r = 3; + *b = ' '; + W r < *w && (x = fgetc(f)) != EOF) { + Q x == '<') { + void **p = Y; + W *p) { + Q X(*p)) { + Q p[1]) + (* (void (*)(c )) + p[1])(*p); + break; + } + p += 2; + } + } else { + Q x == '&') { + G "%9[^;];", T); + x = e(T); + } + P(isspace(x) ? ' ' : x); + } + } + printf("\n? "); + fflush(stdout); + fgets(T, Z, stdin); + Q *T == '\n') + goto e; + t = l[strtol(T, 0, 0)]; + fclose(f); + } + k 0; +} diff --git a/2005/mynx/mynx.c b/2005/mynx/mynx.c index b3d21e644..d0d1f4270 100644 --- a/2005/mynx/mynx.c +++ b/2005/mynx/mynx.c @@ -6,6 +6,9 @@ #define Q if( #define Z 512 #include +#include +#include +#include #include #include #include @@ -147,7 +150,7 @@ main(I V, c *v) struct sockaddr_in A; L = 0; B = 1; - Q (!sscanf(t, "http://%255[^/]%n", h, &n)&&!sscanf(t,"https://%255[^/]%n",h, &n) && !*h)) { + Q !sscanf(t, "http://%255[^/]%n", h, &n) && !*h) { Q !(f = fopen(t, "rb"))) k 1; goto e; diff --git a/2005/mynx/source/mynx.c b/2005/mynx/source/mynx.c new file mode 100644 index 000000000..d0d1f4270 --- /dev/null +++ b/2005/mynx/source/mynx.c @@ -0,0 +1,224 @@ +#define I int +#define c char * +#define G fscanf(f, +#define W while( +#define k return +#define Q if( +#define Z 512 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +FILE *f; +short w[4] = { 24, 80 }; +I L, B, r, H; +c l[Z], b[Z], s[Z], S[Z][10], T[Z], h[Z]; +I +e(c s) +{ + I n = 0; + Q *s == '#') + k (I) strtol(s+1, 0, 0); + W n < Z) { + Q *S[n] && !strcmp(s, S[n]+1)) + k *S[n]; + n++; + } + k '?'; +} +void +P(I x) +{ + Q x == '\n' || w[1] - 3 < B) { + b[B] = 0; + b[B+1] = 0; + B = printf("%s", b); + B = snprintf( + b, Z, + "\n %s", + b + B + 1 + ); + r++; + } + Q b[B-1] != ' ' || !isspace(x)) { + b[B++] = isspace(x) ? ' ' : x; + Q w[1] - 3 < B) + *strrchr(b, ' ') = 0; + } +} +void +p(c t, ...) +{ + va_list x; + va_start(x, t); + vsnprintf(s, Z, t, x); + t = s; + W *t) + P(*t++); + va_end(x); +} +I +X(c s) +{ + I x; + c t = s; + long m = ftell(f); + W *t && (x = fgetc(f)) != EOF) { + Q *t == '*') + s = t++; + Q tolower(x) != *t) { + Q *s != '*') + break; + t = s; + } + t++; + } + Q *t) + fseek(f, m, SEEK_SET); + k !*t; +} +void +d(c s) +{ + Q 4 < B) + P('\n'); + P('\n'); + Q *s == 'h') + B = 1; +} +void +a(c s) +{ + *T = 0; + G + ungetc(fgetc(f), f) == '"' + ? "\"%511[^\"]" + : "'%511[^']", + T + ); + Q *s == 'a' || *s == 'f' || s[1] == 'f') { + free(l[++L]); + l[L] = strdup(T); + p(" [%d] ", L); + } + Q *s != 'a') + p("%s%s\n", T, *s == 'b' || s[1] == 'h' ? "" : "\n"); + X("*>"); +} +void *Y[] = { + "!--*-->" , 0 , + "a *href=" , a , + "ifr*src=" , a , + "fra*src=" , a , + "img*src=" , a , + "p*>" , d , + "bl*>" , d , + "br" , a , + "hr" , a , + "h*>" , d , + "/h" , a , + "/tr" , a , + "/dt" , a , + "/dd" , a , + "li*>" , d , + "*>" , 0 , + 0 , 0 +}; +I +main(I V, c *v) +{ + I x, n = 0; + c t = v[1]; + ioctl(0, TIOCGWINSZ, w); + f = fopen("entities.txt", "r"); + Q f) { + W G "%s %d", S[n]+1, &x) == 2) + *S[n++] = x; + fclose(f); + n = 0; + } + W t) { + I m = 0; + struct hostent *y; + struct sockaddr_in A; + L = 0; + B = 1; + Q !sscanf(t, "http://%255[^/]%n", h, &n) && !*h) { + Q !(f = fopen(t, "rb"))) + k 1; + goto e; + } + Q 0 < sscanf(h, "%*[^:]%n:%d", &x, &H)) + h[x] = 0; + else + H = 80; + y = gethostbyname(h); + Q !y) + k 1; + memcpy(&A.sin_addr.s_addr, y->h_addr, y->h_length); + A.sin_port = htons( (short) H); + A.sin_family = y->h_addrtype; + f = tmpfile(); + Q !f) + k 1; + W + connect( + m = socket( + A.sin_family, SOCK_STREAM, 0 + ), (void *) &A, sizeof A + ) + || errno == EINTR + ) + ; + n = snprintf( + b, Z, + "GET %s%s HTTP/1.0\r\nHost: %s:%d\r\n\r\n", + t[n] == '/' ? "" : "/", t+n, h, H + ); + Q send(m, b, n, 0) == n) { + W 0 < (n = recv(m, b, Z, 0))) + fwrite(b, 1, n, f); + } + close(m); + rewind(f); + X("*\r\n\r\n"); +e: + r = 3; + *b = ' '; + W r < *w && (x = fgetc(f)) != EOF) { + Q x == '<') { + void **p = Y; + W *p) { + Q X(*p)) { + Q p[1]) + (* (void (*)(c )) + p[1])(*p); + break; + } + p += 2; + } + } else { + Q x == '&') { + G "%9[^;];", T); + x = e(T); + } + P(isspace(x) ? ' ' : x); + } + } + printf("\n? "); + fflush(stdout); + fgets(T, Z, stdin); + Q *T == '\n') + goto e; + t = l[strtol(T, 0, 0)]; + fclose(f); + } + k 0; +} diff --git a/2005/persano/.gitignore b/2005/persano/.gitignore index 16dd750ad..b950a579f 100644 --- a/2005/persano/.gitignore +++ b/2005/persano/.gitignore @@ -1 +1,2 @@ persano +foo.gif diff --git a/2005/persano/README.md b/2005/persano/README.md index ba6f18e59..dafb9e408 100644 --- a/2005/persano/README.md +++ b/2005/persano/README.md @@ -1,9 +1,8 @@ # Best of show - Mauro Persano - São Paulo - Brazil - mauro_persano@yahoo.com +Mauro Persano +Brazil + ## To build: @@ -23,10 +22,11 @@ make ./persano 3 16 > knot3-16.gif ``` -Open the GIF file with a viewer capable of displaying animated GIFs and -watch closely at the bottom of the picture (you may need to use -"gifsicle" - a great tool to manipulate animated GIFs - to slow down the -animation and to compress the GIFs generated by the entry). +Open the [GIF](https://en.wikipedia.org/wiki/GIF) file with a viewer capable of +displaying animated GIFs and watch closely at the bottom of the picture (you may +need to use [gifsicle](https://www.lcdf.org/gifsicle/) - a great tool to +manipulate animated GIFs - to slow down the animation and to compress the GIFs +generated by the entry). ## Judges' remarks: @@ -39,31 +39,32 @@ What needs to be done to fix the problem? Solving the author's exercises below may or may not help. -At the time of judging, the approximation of π used in the program could -not be found on mathworld.com. +At the time of judging, the approximation of +[π](https://en.wikipedia.org/wiki/Pi) used in the program could not be found on +. ## Author's remarks: -### NAME -**knot** -> writes animated GIF images of rendered torus knots to standard output. +**knot** writes animated GIF images of rendered [torus +knots](https://en.wikipedia.org/wiki/Torus_knot) to standard output. ### SYNOPSIS ```sh -knot p q [num frames] +./persano p q [num frames] ``` ### DESCRIPTION -A (p,q)-torus knot is a closed, non-intersecting curve on the surface of -a torus in R3 that winds p times around one cycle of the torus and q -times around the other. p and q should be coprime; otherwise, the -resulting curve will _not_ be a knot (that is, imagining the resulting -curve as a loop of rubber, there will be a way to bend, twist and -stretch it, without cutting it [1], until it ends up looking just like a -circle embedded in R3 [2]). +A (p,q)-[torus knot](https://en.wikipedia.org/wiki/Torus_knot) is a closed, +non-intersecting curve on the surface of a +[torus](https://en.wikipedia.org/wiki/Torus) in R3 that winds `p` times around +one cycle of the torus and `q` times around the other. `p` and `q` should be +[coprime](https://en.wikipedia.org/wiki/Coprime_integers); otherwise, the +resulting curve will _not_ be a knot (that is, imagining the resulting curve as +a loop of rubber, there will be a way to bend, twist and stretch it, without +cutting it [1], until it ends up looking just like a circle embedded in R3 [2]). Sample usage: @@ -72,13 +73,14 @@ Sample usage: ``` writes a non-animated GIF (a single frame) stream of a rendered trefoil -knot to the file foo.gif. +knot to the file `foo.gif`. ```sh ./persano 5 2 ``` -writes a GIF stream with a rendering of Solomon's Seal knot to standard +writes a GIF stream with a rendering of [Solomon's Seal +knot](https://en.wikipedia.org/wiki/Solomon%27s_knot) to standard output; since the number of frames is not specified, an animation with 40 frames will be written. @@ -91,9 +93,10 @@ The program writes fully valid GIF 89 streams. It is suggested that the output be viewed with a program capable of displaying animated GIFs, such as almost any graphical HTTP browser. -Due to code size constraints, full LZW compression was not implemented -[3]. In fact, the output images are even somewhat expanded, thanks to -GIF overhead. +Due to code size constraints, full [LZW +compression](https://en.wikipedia.org/wiki/LZ77_and_LZ78#LZW) was not +implemented [3]. In fact, the output images are even somewhat expanded, thanks +to GIF overhead. The GIF format supports only a limited number of bits per pixel, so the program uses ordered dithering to emulate full RGB output. @@ -101,7 +104,7 @@ program uses ordered dithering to emulate full RGB output. ### PORTABILITY The program was tested on Linux, with gcc 3.1; Cygwin, with gcc 3.3; and -Solaris/Sparc, with Sun's C compiler. +Solaris/SPARC, with Sun's C compiler. The only major portability issue should be reliance on ASCII. @@ -111,12 +114,13 @@ anyone uses such systems in this day and age, this is a minor issue. [4] ### EXERCISES FOR THE READER - 1. (1 point) The surface is composed of many small polygons. Try to make it +1. (1 point) The surface is composed of many small polygons. Try to make it smoother by increasing the number of polygons. - 2. (2 points) Figure out how to change the radius of the tube cross section. +2. (2 points) Figure out how to change the radius of the tube cross section. - 3. (5 points) Locate the famous transcendental constant π in the code. +3. (5 points) Locate the famous transcendental constant +[π](https://en.wikipedia.org/wiki/Pi) in the code. ### FOOTNOTES diff --git a/2005/sykes/.gitignore b/2005/sykes/.gitignore index dfb07295f..36e58b512 100644 --- a/2005/sykes/.gitignore +++ b/2005/sykes/.gitignore @@ -1,2 +1,3 @@ pet.rom sykes +dungeon.prg diff --git a/2005/sykes/README.md b/2005/sykes/README.md index df71014eb..b73963264 100644 --- a/2005/sykes/README.md +++ b/2005/sykes/README.md @@ -1,11 +1,8 @@ # Best emulator - Stephen Sykes - Maxisat - Laivalahdenportti 2 - 00810, Helsinki - Finland - sds@maxisat.fi +Stephen Sykes + + ## To build: @@ -23,34 +20,54 @@ make ```sh ./sykes pet.rom +# type in the following for an old Easter egg: +WAIT 6502,12 ``` +Also try: + +``` +./sykes chess +``` + +for some good [chess](https://en.wikipedia.org/wiki/Chess) fun. + ## Judges' remarks: -For those who fondly remember their first PET, this entry will start you -down memory lane ... starting with $C000 of course! +For those who fondly remember their first +[PET](https://en.wikipedia.org/wiki/Commodore_PET), this entry will start you +down memory lane ... starting with `$C000` of course! -We encourage you to try and grok the obfuscated expression on line 56, -after C pre-processor gets finished with it! +We encourage you to try and grok the obfuscated expression on [line +56](https://github.com/ioccc-src/temp-test-ioccc/blob/master/2005/sykes/sykes.c#L56), +after the C pre-processor gets finished with it! -We download the ROM contents to use the emulator in PET mode as follows: +We downloaded the [ROM](https://en.wikipedia.org/wiki/ROM_image) contents to use +the [emulator](https://en.wikipedia.org/wiki/Emulator) in +[PET](https://en.wikipedia.org/wiki/Commodore_PET) mode as follows: - wget http://www.zimmers.net/anonftp/pub/cbm/firmware/computers/pet/basic-2-c000.901465-01.bin - wget http://www.zimmers.net/anonftp/pub/cbm/firmware/computers/pet/basic-2-d000.901465-02.bin - wget http://www.zimmers.net/anonftp/pub/cbm/firmware/computers/pet/edit-2-n.901447-24.bin - wget http://www.zimmers.net/anonftp/pub/cbm/firmware/computers/pet/kernal-2.901465-03.bin +```sh +wget http://www.zimmers.net/anonftp/pub/cbm/firmware/computers/pet/basic-2-c000.901465-01.bin +wget http://www.zimmers.net/anonftp/pub/cbm/firmware/computers/pet/basic-2-d000.901465-02.bin +wget http://www.zimmers.net/anonftp/pub/cbm/firmware/computers/pet/edit-2-n.901447-24.bin +wget http://www.zimmers.net/anonftp/pub/cbm/firmware/computers/pet/kernal-2.901465-03.bin +``` We then created: - dd bs=2k count=1 if=/dev/zero of=nullfill.bin +```sh +dd bs=2k count=1 if=/dev/zero of=nullfill.bin +``` For your convenience, we have added the above mentioned files to this entry directory. -They are used to form the pet.rom file. +They are used to form the `pet.rom` file. ## Author's remarks: -This program is not only a complete 6502 processor emulator, but also an -emulation of the Commodore PET 2001. +This program is not only a complete [Motorola 6502 +processor](https://en.wikipedia.org/wiki/MOS_Technology_6502#Technical_description) +[emulator](https://en.wikipedia.org/wiki/Emulator), but also an emulation of the +[Commodore PET 2001](https://en.wikipedia.org/wiki/Commodore_PET). This is the second version of the same entry, but this one takes care to not include any possibly copyrighted items in the info files, to be sure @@ -58,7 +75,9 @@ to not infringe the rules. ### Test -Compile the program, then test the 6502 emulation like this: +Compile the program, then test the +[6502](https://en.wikipedia.org/wiki/MOS_Technology_6502#Technical_description) +[emulation](https://en.wikipedia.org/wiki/Emulator) like this: ```sh ./sykes 6502test @@ -70,38 +89,31 @@ control-C. ### PET EMULATION -Cast your mind back to 1977... a little company called Commodore -introduced the "PET", the Personal Electronic Transactor. +Cast your mind back to 1977... a little company called +[Commodore](https://en.wikipedia.org/wiki/Commodore_International) introduced +the [PET](https://en.wikipedia.org/wiki/Commodore_PET), the Personal Electronic +Transactor. -The machine was a hit, and history was made. +The [machine](https://en.wikipedia.org/wiki/Computer) was a hit, and +[history](https://en.wikipedia.org/wiki/History) was made. -Now you can re-live those wonderful times with this PET emulator! +Now you can relive those wonderful times with this +[PET](https://en.wikipedia.org/wiki/Commodore_PET) emulator! -To emulate the PET, you must download the pet rom. Use the script -provided (fetchrom), it will fetch the parts from right place, and will -compile it into the file pet.rom. - -Or if you don't have wget, navigate to here: - - - -and fetch the files basic-2-c000.901465-01.bin, -basic-2-d000.901465-02.bin, edit-2-n.901447-24.bin, -kernal-2.901465-03.bin. Concatenate them in that order into one pet.rom -file, adding a 2048 byte filler in between the edit-2 and kernal-2 -files. The resulting file should be 16384 bytes. - -Make sure you have a terminal window of 40x25 chars or bigger, and then -run the emulator like this: +Make sure you have a [terminal +window](https://en.wikipedia.org/wiki/Terminal_emulator) of 40x25 chars or +bigger, and then run the emulator like this: ```sh ./sykes pet.rom ``` -You should see the startup message. Try typing in some BASIC - for -instance: +You should see the startup message. Try typing in some +[BASIC](https://en.wikipedia.org/wiki/BASIC) - for instance: - PRINT "HELLO, WORLD" +``` +PRINT "HELLO, WORLD" +``` There is an optional numeric parameter, which controls the speed. For a slower cursor blink, try @@ -116,10 +128,11 @@ and for faster ./sykes pet.rom 2 ``` -the default is 4. +The default is 4. The control keys are as follows: +``` ^A HOME ^L CLR ^R RVS @@ -129,13 +142,17 @@ The control keys are as follows: ^F cursor forward ^B cursor back ^N cursor down +``` -Supplied also is a short demo program written in BASIC. Try typing +Supplied also is a short demo program written in +[BASIC](https://en.wikipedia.org/wiki/BASIC). Try typing - LOAD "DEMO" - RUN +``` +LOAD "DEMO" +RUN +``` -Many other old programs will run in this emulator too. Files with a .PRG +Many other old programs will run in this emulator too. Files with a `.PRG` extension should work. (Look, for instance, here: , or try this one: ) @@ -143,24 +160,34 @@ The filenames must be upper case in order to be loaded by the emulator. You can save programs too - try - 10 PRINT "HELLO!" - SAVE "HELLO" - NEW +``` +10 PRINT "HELLO!" +SAVE "HELLO" +NEW - LOAD "HELLO" - RUN +LOAD "HELLO" +RUN +``` -You also might try typing this to see an ancient easter egg: +You also might try typing this to see an ancient [Easter egg][]: - WAIT 6502,12 +``` +WAIT 6502,12 +``` + +[Easter egg]: https://en.wikipedia.org/wiki/Easter_egg_(media)#Software ### 6502 EMULATION -The program is basically a 6502 emulator, and it does NOT need the -commodore rom to work. +The program is basically a +[6502](https://en.wikipedia.org/wiki/MOS_Technology_6502#Technical_description) +[emulator](https://en.wikipedia.org/wiki/Emulator), and it does NOT need the +[commodore](https://en.wikipedia.org/wiki/Commodore_PET) +[rom](https://en.wikipedia.org/wiki/ROM_image) to work. -Supplied as a demonstration is a compiled-for-6502 version a chess -program (heh, I found a use for a previous losing entry :). Try: +Supplied as a demonstration is a +compiled-for-[6502](https://en.wikipedia.org/wiki/MOS_Technology_6502#Technical_description) +version a chess program (heh, I found a use for a previous losing entry :) ). Try: ```sh ./sykes chess @@ -169,73 +196,104 @@ program (heh, I found a use for a previous losing entry :). Try: It works as you would expect (it plays very badly). There's no castling or en-passant, and to win you must actually take the opponent's king. -You can write your own programs too, any 6502 assembler should work. +You can write your own programs too, any [6502 +assembler](https://en.wikibooks.org/wiki/6502_Assembly) should work. -The emulator loads the supplied file at $C000, and starts execution from -that address also (the reset vector is ignored). +The [emulator](https://en.wikipedia.org/wiki/Emulator) loads the supplied file +at `$C000`, and starts execution from that address also (the reset vector is +ignored). -The screen memory begins at $8000, and is 40 columns * 25 rows. -Keypresses appear when they occur in memory location $A2, and are OR'd -with $80 - this is a way of indicating a fresh character. The program +The screen memory begins at `$8000`, and is `40 columns * 25 rows`. +Key presses appear when they occur in memory location `$A2`, and are +[OR](https://en.wikipedia.org/wiki/Bitwise_operation#OR)ed +with `$80` - this is a way of indicating a fresh character. The program can frequently check this byte, and when it sees a new character, it can -AND it with $7F to indicate that it has been read. +[AND](https://en.wikipedia.org/wiki/Bitwise_operation#AND) it with `$7F` to +indicate that it has been read. -The 6502 emulator receives an interrupt 60 times a second or so, you may -want to disable interrupts (with SEI) if you do not need this. +The +[6502](https://en.wikipedia.org/wiki/MOS_Technology_6502#Technical_description) +[emulator](https://en.wikipedia.org/wiki/Emulator) receives an interrupt 60 +times a second or so, you may want to disable interrupts (with the `SEI` +instruction) if you do not need this. -In 6502 emulation mode the special PET character codes are not used and -the screen understands normal ASCII. +In +[6502](https://en.wikipedia.org/wiki/MOS_Technology_6502#Technical_description) +[emulation](https://en.wikipedia.org/wiki/Emulator) mode the special +[PET](https://en.wikipedia.org/wiki/Commodore_PET) character codes are not used and +the screen understands normal +[ASCII](https://en.wikipedia.org/wiki/ASCII#Character_set). -Lastly, the before emulation starts, the low byte from a time() call is -placed at address 0 - this can be used as a random seed. +Lastly, the before [emulation](https://en.wikipedia.org/wiki/Emulator) starts, +the low byte from a `time()` call is placed at address 0 - this can be used as a +random seed. ### Technical description -Most of the program comprises the 6502 emulator. Curses is used for the +Most of the program comprises the +[6502](https://en.wikipedia.org/wiki/MOS_Technology_6502#Technical_description) +[emulator](https://en.wikipedia.org/wiki/Emulator). `curses` is used for the screen and keyboard handling. -Much of the obfuscation comes from the need to squeeze in the 6502 -emulation as well as faking enough of the PET hardware for it to work. +Much of the obfuscation comes from the need to squeeze in the +[6502](https://en.wikipedia.org/wiki/MOS_Technology_6502#Technical_description) +[emulation](https://en.wikipedia.org/wiki/Emulator) as well as faking enough of +the [PET](https://en.wikipedia.org/wiki/Commodore_PET) hardware for it to work. -If the supplied file is exactly 16384 bytes, the emulator assumes it is -a PET rom, and goes into PET emulation mode. Otherwise some PET specific -features are skipped during normal 6502 emulation. +If the supplied file is exactly 16384 bytes, the +[emulator](https://en.wikipedia.org/wiki/Emulator) assumes it is a +[PET](https://en.wikipedia.org/wiki/Commodore_PET) +[rom](https://en.wikipedia.org/wiki/ROM_image), and goes into PET emulation +mode. Otherwise some PET specific features are skipped during normal +[6502](https://en.wikipedia.org/wiki/MOS_Technology_6502#Technical_description) +[emulation](https://en.wikipedia.org/wiki/Emulator). The main processing all happens in a heroic expression containing no -less than 64 ternery operators (after cpp) starting on line 56. This -decodes the 6502 instructions according to a table and executes them. +less than 64 ternary operators (after `cpp`) starting on line 56. This +decodes the +[6502](https://en.wikipedia.org/wiki/MOS_Technology_6502#Technical_description) +instructions according to a table and executes them. The addressing mode is decoded in a similar expression starting on line 53. ### Bugs -The machine emulated is an older 40 column PET, so 80 column programs +The machine emulated is an older 40 column +[PET](https://en.wikipedia.org/wiki/Commodore_PET), so 80 column programs will not show correctly. -There is no emulation of PET graphics characters. +There is no [emulation](https://en.wikipedia.org/wiki/Emulator) of +[PET](https://en.wikipedia.org/wiki/Commodore_PET) graphics characters. The parameter controls the speed of the 60Hz "jiffy clock", and not the processor speed. This means many games may run too fast to be usable - it really depends on the speed of your machine. -Although the PET emulator can do LOAD and SAVE, it cannot VERIFY or OPEN -and CLOSE files. +Although the PET [emulator](https://en.wikipedia.org/wiki/Emulator) can do LOAD +and SAVE, it cannot VERIFY or OPEN and CLOSE files. -The PET hardware emulation is not at all complete - features such as the -hardware timers are completely missing. Some programs will not run -correctly. +The [PET](https://en.wikipedia.org/wiki/Commodore_PET) hardware +[emulation](https://en.wikipedia.org/wiki/Emulator) is not at all complete - +features such as the hardware timers are completely missing. Some programs will +not run correctly. -The 6502 emulation does not include the seldom used decimal mode, or any -of the "undocumented" instructions. +The +[6502](https://en.wikipedia.org/wiki/MOS_Technology_6502#Technical_description) +[emulation](https://en.wikipedia.org/wiki/Emulator) does not include the seldom +used decimal mode, or any of the "undocumented" instructions. ### IMPORTANT NOTE -I think it is great fun to run the PET emulation and mess around with -Microsoft BASIC. However, this obviously needs the rom file to work. My +I think it is great fun to run the +[PET](https://en.wikipedia.org/wiki/Commodore_PET) +[emulation](https://en.wikipedia.org/wiki/Emulator) and mess around with +[Microsoft](https://en.wikipedia.org/wiki/Microsoft) +[BASIC](https://en.wikipedia.org/wiki/BASIC). However, this obviously needs the +[rom](https://en.wikipedia.org/wiki/ROM_image) file to work. My program is original and completely free of any copyright, but, of -course, the pet rom is not my work. So I ask the user to download it -from the internet. This is to avoid directly infringing any copyright. +course, the `pet.rom` is not my work. So I ask the user to download it +from the Internet. This is to avoid directly infringing any copyright. ### Finally diff --git a/2005/timwi/README.md b/2005/timwi/README.md index 79fed70c2..836b06e34 100644 --- a/2005/timwi/README.md +++ b/2005/timwi/README.md @@ -1,8 +1,8 @@ # Most discourteous interpreter - Arne "Timwi" Heizmann - Germany - timwi@gmx.net +Arne "Timwi" Heizmann +Germany + ## To build: @@ -24,40 +24,43 @@ make ## Judges' remarks: -Unlike most BF interpreters that we have been receiving for the last few -years, this one, in our opinion, is the most obfuscated albeit the most -discourteous to the language it interprets. A simple 3-character fix will make -it slightly less so. +Unlike most [BF](https://en.wikipedia.org/wiki/Brainfuck) interpreters that we +have been receiving for the last few years, this one, in our opinion, is the +most obfuscated albeit the most discourteous to the language it interprets. A +simple 3-character fix will make it slightly less so. Quite a few BF programs found on the Net expect byte-based memory, quite a few exceed the capacity of this interpreter, but there are many that work. Some -small quines work, some don't. +small [quines][] work, some don't. Why? +[quines]: https://en.wikipedia.org/wiki/Quine_(computing) + ## Author's remarks: -This is an interpreter for the programming language BrainFuck (BF). +This is an interpreter for the programming language +[BrainFuck](https://en.wikipedia.org/wiki/Brainfuck) (BF). Input must be provided in the following format: First a sequence of integers -separated by whitespace (this will be the input to the BF program), then a -colon (:), then the BF program itself. +separated by whitespace (this will be the input to the BF program), then a `:` +(colon), then the BF program itself. You must not pass any command-line arguments. ### Features - * Supports the complete set of 8 BF instructions (+-<>[].,). - * Supports the use of alternative characters for some of those instructions. +* Supports the complete set of 8 BF instructions (`+-<>[].,`). +* Supports the use of alternative characters for some of those instructions. Use this to obfuscate your BF programs! -For a challenge, figure out what this obfuscated BF program does: + For a challenge, figure out what this obfuscated BF program does: - J4mzt?Vazexx-20d~&&~AxdUV!x(~Jz&V)x*(P=J)JUN(dizz)xx_!xx'0&{Vz;}&Jj + J4mzt?Vazexx-20d~&&~AxdUV!x(~Jz&V)x*(P=J)JUN(dizz)xx_!xx'0&{Vz;}&Jj -It takes two integers as input and outputs one integer. + It takes two integers as input and outputs one integer. - * Ignores all whitespace (newlines, spaces and tabs) in the input program. +* Ignores all whitespace (newlines, spaces and tabs) in the input program. ### Limitations @@ -70,13 +73,13 @@ one of these limits, the behaviour is undefined. ### Obfuscations -Some of the superficial obfuscations are pretty obvious: I'm using #defines to -make everything look nice and liney, and the program is merely a recursive -main function with only a single 'return' statement which uses nested ternary +Some of the superficial obfuscations are pretty obvious: I'm using `#define`s to +make everything look nice and lineal, and the program is merely a recursive +`main` function with only a single `return` statement which uses nested ternary operators to make even the pre-processed code unreadable. However, the more subtle obfuscations relate to the way the program works. -After applying the pre-processing, you will see a lot of "1+1+1+...etc.", and +After applying the pre-processing, you will see a lot of `1+1+1`...etc., and even if you replace these with their result, those numbers will still not represent (or even relate to) the ASCII codes of the BF instructions. diff --git a/2005/toledo/README.md b/2005/toledo/README.md index a69de23e1..b24d454cb 100644 --- a/2005/toledo/README.md +++ b/2005/toledo/README.md @@ -1,12 +1,9 @@ # Best game - Oscar Toledo G. - Familia Toledo - Av. Santa Cruz del Monte 9-304 - Ciudad Satelite Edo de Mexico - CP 53110 - Mexico - uno@biyubi.com +Oscar Toledo G. +Familia Toledo +Mexico + ## To build: @@ -29,7 +26,8 @@ make ## Alternate code: -An alternate version of this entry, `toledo2.c` and `toledo3.c` is provided. +Two alternate versions of this entry, [toledo2.c](toledo2.c) and +[toledo3.c](toledo3.c) are provided. To compile these alternate versions: @@ -37,12 +35,12 @@ To compile these alternate versions: make alt ``` -Use `toledo2` or `toledo3` as you would `toledo` above. +Use `toledo2` and `toledo3` as you would `toledo` above. ## Judges' remarks: Challenge yourself with your ability to look 5, 6 or more moves ahead. -Challenge your knowledge of C operator precedence. The following the +Challenge your knowledge of C operator precedence. The following is the move analysis via recursion while it executes moves. All while playing by the rules of C and Chess within a single function! @@ -50,50 +48,54 @@ by the rules of C and Chess within a single function! ### What does this program -This is a chess program, it can work in two modes: two-players, and one player -(always white) against the machine. To get the first mode, run the program -without arguments: +This is a [chess](https://en.wikipedia.org/wiki/Chess) program, it can work in +two modes: two-players, and one player (always white) against the machine. To +get the first mode, run the program without arguments: ```sh ./toledo ``` -The other mode is accesible running the program with one argument (5-ply +The other mode is accessible running the program with one argument +(5-[ply](https://en.wikipedia.org/wiki/Ply_(game_theory)) analysis): ```sh ./toledo a ``` -Two arguments for 6-ply analysis: +Two arguments for 6-[ply](https://en.wikipedia.org/wiki/Ply_(game_theory)) +analysis: ```sh ./toledo a b ``` -And each succesive argument will analyze one ply more. There is no ply limit, -but beyond 7 ply is very slow, try it at your own risk and computing time. +And each successive argument will analyze one +[ply](https://en.wikipedia.org/wiki/Ply_(game_theory)) more. There is no ply +limit, but beyond 7 ply is very slow, try it at your own risk and computing +time. ### Entering movements -When is your turn, you can enter your move, by example, as "d2d4" (without the -quotes) and press the Enter key, the computer will check move legality and -will warn you of illegal moves. All legal chess moves are permitted. +When is your turn, you can enter your move, by example, as `d2d4` and press the +enter key. The computer will check move legality and will warn you of illegal +moves. All legal chess moves are permitted. One special case is when you are doing promotion, you must enter the move with an extra letter indicating the desired piece. -By example "f7f8n" (supossing you have a pawn on f7), will promote it to a -knight, substitute 'n' for the desired piece (N/Q/R/B). +By example `f7f8n` (supposing you have a pawn on `F7`), will promote it to a +knight; substitute `n` for the desired piece (`N`/`Q`/`R`/`B`). -Note that the program requires the piece letter, it will not select +Note that the program requires the piece letter; it will not select automatically a queen, so don't be surprised if it doesn't accept your move. ### Game status -The computer will check for checkmate and stalemate, also after each machine -move, it will show the score of the position, an higher number is better for -the computer, i.e. worst for you. +The computer will check for checkmate and stalemate. Also, after each machine +move, it will show the score of the position: a higher number is better for +the computer, i.e. worse for you. ### Quirks @@ -105,35 +107,43 @@ This is a good example of a chess program reduced to the essential. In order to get it into the contest limits, I used short but slow and unintelligible algorithms. -The interface accounts for only a fraction of the code, the core does -multiples functions, it is called recursively to analyze and evaluate each -ply, does alpha-beta cutting, move generation, machine playing, check -detection, illegal move verification and does moves after they are verified. +The interface accounts for only a fraction of the code, the core does multiples +functions: it is called recursively to analyze and evaluate each +[ply](https://en.wikipedia.org/wiki/Ply_(game_theory)), does [alpha-beta +pruning](https://en.wikipedia.org/wiki/Alpha-beta_pruning), move generation, +machine playing, check detection, illegal move verification and does moves after +they are verified. -Also sets an standard on ultra-mini-chess programs, the player and the -computer can do all legal chess moves, other features are: +It also sets a standard on ultra-mini-chess programs. The player and the +computer can do all legal chess moves. - * Illegal move verification. - * Checkmate detection. - * Stalemate detection. - * Computer is tough (check 7-ply), even in 5 ply can give a surprise to +### Additional features + +Other features are: + +* Illegal move verification. +* [Checkmate](https://en.wikipedia.org/wiki/Checkmate) detection. +* Stalemate detection. +* Computer is tough (check +7-[ply](https://en.wikipedia.org/wiki/Ply_(game_theory))) and even in 5 ply can give a surprise to amateur players. -### Obsfucation tricks +### Obfuscation tricks - * Only one C function, really modular. - * Extensive use of the trinary and comma operators, save a hard drive today. - * Extensive use of C operator precedence, all good C programmers remember +* Only one very modular C function. +* Extensive use of the ternary and comma operators; save a hard drive today. +* Extensive use of C operator precedence; all good C programmers remember it... I cannot. - * Exchanged operands every place is possible, someday someone will -understand it, - * Mixed and multifunction expressions on statements, in good old-BASIC +* Exchanged operands every place possible. Someday someone will +understand it. +* Mixed and multifunction expressions on statements, in good old-BASIC style. - * Macros used to hide C syntax, check unballanced parenthesis and calls with +* Macros used to hide C syntax: check unbalanced parenthesis and calls with empty arguments! - * Only includes strictly necessary standard headers, the linker takes care, +* Only includes strictly necessary standard headers, the linker takes care, and compiles faster... but I'm still not seeing the difference. - * Uses only one string, very easy to I18N ;) +* Uses only one string, very easy to +[i18n](https://en.wikipedia.org/wiki/Internationalization_and_localization) ;) ## Copyright and CC BY-SA 4.0 License: diff --git a/2005/vik/README.md b/2005/vik/README.md index 8f61802e8..455ab95ce 100644 --- a/2005/vik/README.md +++ b/2005/vik/README.md @@ -1,10 +1,9 @@ # Most circuitous walk - Daniel Vik - 926 Genter Street - La Jolla Ca 92037 - USA - daniel@vik.cc +Daniel Vik +US + + ## To build: @@ -26,50 +25,70 @@ make ## Judges' remarks: -An amazing use of the X libraries with twisty code passages, -all different. One risks running in code path circles as main is -called again and again. Be sure to pay attention to commas! :-) +An amazing use of the X libraries with twisty code passages, all different. One +risks running in code path circles as `main()` is called again and again. Be +sure to pay attention to commas! :-) ## Author's remarks: -This entry is a Wolfenstein style graphics engine where a user can navigate in -a 3D world. The maze has walls with bitmap textures. The application contains -a default world with textures, but the power of the engine is exposed through -user configured maps. User defined worlds support up to 26 different wall -textures that can even be animated. One example of a user defined world is -submitted with the entry. +This entry is a [Wolfenstein](https://en.wikipedia.org/wiki/Wolfenstein) style +[graphics engine](https://en.wikipedia.org/wiki/Rendering_(computer_graphics)) +where a user can navigate in a +[3D](https://en.wikipedia.org/wiki/3D_computer_graphics) world. The +[maze](https://en.wikipedia.org/wiki/Maze) has walls with [bitmap +textures](https://en.wikipedia.org/wiki/Bitmap_textures). The application +contains a default world with textures, but the power of the engine is exposed +through user configured [maps](https://en.wikipedia.org/wiki/Map). User defined +worlds support up to 26 different wall textures that can even be animated. One +example of a user defined world is submitted with the entry. ### Features This program is a complete 3D engine with - * Easy configurable maze maps - * Up to 26 different bitmap textures in a maze - * Support for animated bitmap textures - * Uses default bitmaps in case the configured bitmaps can't be found - * A default map in case no one is specified - * Configurable window size - * Navigation using cursor keys (rotate left and right, move forward and -backward) +* Easy configurable maze maps. +* Up to 26 different bitmap textures in a maze. +* Support for animated bitmap textures. +* Uses default bitmaps in case the configured bitmaps can't be found. +* A default map in case no one is specified. +* Configurable window size. +* Navigation using cursor keys (rotate left and right, move forward and +backward). ### Build and Run -Compile the source code and link x libraries if necessary. The program takes +Compile the source code and link [x +libraries](https://en.wikipedia.org/wiki/Xlib) if necessary. The program takes three options which have to be typed in a specific order as described below. - Usage: prog [-w ] [mapfile] +``` + Usage: ./vik [-w ] [mapfile] width - Specifies the width of the window mapfile - Filename containing a map +``` -Here are a few examples: +#### Examples -> | Command line: | Description: | -> | ------------------------ | ---------------------- | -> | $ ./prog | Starts the engine using a built in labyrinth and texture bitmaps | -> | $ ./prog maze.map | Starts the engine and loads the labyrinth defined in the file maze.map | -> | $ ./prog -w 400 maze.map | Starts the engine using maze.map in a window that is 400 pixels wide | +Start the engine using a built in labyrinth and texture bitmaps: -Note that the mapfile has to be the last argument and the -w option if present +```sh +./vik +``` + +Start the engine and loads the labyrinth defined in the file +[maze.map](maze.map): + +```sh +./vik maze.map +``` + +Start the engine using [maze.map](maze.map) in a window that is 400 pixels wide: + +```sh +./vik -w 400 maze.map +``` + +Note that the `mapfile` has to be the last argument and the `-w` option if present has to be the first. The map definition files and the bitmap files should be located in the current directory. @@ -78,10 +97,11 @@ Use the cursor keys to navigate through the labyrinth. ### Creating mazes A maze consist of a map file and texture bitmap files. The map file is an -ascii text file where lower case letters represent walls. The letter tells the -engine what bitmap texture file to use. The `'*'` character lets the engine know +ASCII text file where lower case letters represent walls. The letter tells the +engine what bitmap texture file to use. The `*` character lets the engine know where to position the user. The example below shows how a map file can look: +``` aaaaaaaaaaaaa a a a * a @@ -89,7 +109,9 @@ where to position the user. The example below shows how a map file can look: c c cccccccccccccccccccc -The engine loads the map, and creates walls. When a character 'a'-'z' is found, +``` + +The engine loads the map, and creates walls. When a character `a`-`z` is found, the engine will load the corresponding texture bitmap. The bitmap file must be named `*.bmp` where `*` is substituted with the letter of the wall in the map. @@ -99,24 +121,30 @@ current directory). ### Obfuscation -The program is obfuscated in several ways, bad use of variables, use of the `?` -operator, recursive calls to main, bad use of for variables and the comma -operator. To make the final obfuscated touch I ran indent which really made -the program unreadable (I guess that is not really the intent with indent ;) +The program is obfuscated in several ways: + +* Bad use of variables. +* Use of the `?` operator. +* Recursive calls to `main()`. +* Bad use of for variables and the comma operator. +* To make the final obfuscated touch I ran indent which really made the program +unreadable (I guess that is not really the intent with indent ;) ) ### Compiler warnings -There are no compiler warnings when compiling with -ansi but there are quite -many warnings from lclint. Mainly because the program is very optimized for +There are no compiler warnings when compiling with `-ansi` but there are quite +a few warnings from `lclint`. Mainly because the program is very optimized for code size. ### Limitations -The program only compiles and runs on X based systems. +The program only compiles and runs on [X based +systems](https://en.wikipedia.org/wiki/X_Window_System). -The program does not run that smooth under cygwin. It seems to be a priority -issue with cygwin and it can easily be solved by increasing the priority of -the application a little bit. +The program does not run that smooth under +[Cygwin](https://en.wikipedia.org/wiki/Cygwin). It seems to be a priority issue +with Cygwin and it can easily be solved by increasing the priority of the +application a little bit. ## Copyright and CC BY-SA 4.0 License: diff --git a/2005/vince/README.md b/2005/vince/README.md index 9b0200535..25ec96126 100644 --- a/2005/vince/README.md +++ b/2005/vince/README.md @@ -1,10 +1,9 @@ # Most beauteous visuals - Vincent Weaver - Ithaca, NY - USA - vince@deater.net - +Vincent Weaver +US + + ## To build: @@ -21,7 +20,8 @@ make ./vince ``` -Under MacOSX run from within an xterm while the X11 server is running. +Under macOS run from within an console tab (whether xterm, the default or +another) while the X11 server is running. ## Try: @@ -31,8 +31,8 @@ echo "Do or do not. There is no try." ### Alternate code: -The `vince.alt.c` code of the submission will run on SGI Irix and -also has the recursive CPP macro (which snuck in accidentally) removed. +The [vince.alt.c](vince.alt.c) code of the submission will run on SGI IRIX and +also has the recursive CPP macro (which sneaked in accidentally) removed. To compile this alternate version: @@ -44,9 +44,12 @@ Use `vince.alt` as you would `vince` above. ## Judges' remarks: -This beauteous entry makes use of visual {}'s and whitespace to instruct -the OpenGL development libraries to create beauteous visuals. Even -hitting the space bar while the program runs produces a "spacey" effect! :-) +This beauteous entry makes use of visual `{}`s and whitespace to instruct the +[OpenGL](https://www.opengl.org) development libraries to create beauteous +visuals. Even hitting the space bar while the program runs produces a "spacey" +effect! :-) + +NOTE: when hitting space bar make sure that the program window is in focus! Challenge: Try modifying the texture to something of your own design. @@ -54,23 +57,23 @@ Challenge: Try modifying the texture to something of your own design. ### ABUSE OF RULES - * The executable needs to read in its own source code in order to run. As +* The executable needs to read in its own source code in order to run. As long as the source is in the same directory as the executable it should be able to find it... - * The program requires the OpenGL library. +* The program requires the OpenGL library. - * The program abuses severely the whitespace and { } ; exceptions in the -filesize limits. +* The program abuses severely the whitespace and `{ } ;` exceptions in the +file size limits. ### Requirements - * OpenGL. It works (slowly) with Mesa. +* OpenGL. It works (slowly) with Mesa. - * 16bpp graphics capability (but might work at other depths) +* 16bpp graphics capability (but might work at other depths) - * The original source needs to be in the same directory as the executable, -and the source's name should be the same as the executable but with .c on the +* The original source needs to be in the same directory as the executable, +and the source's name should be the same as the executable but with `.c` on the end. ### Background @@ -86,7 +89,7 @@ rendering. ### Obfuscation It was a challenge getting the source code below the 2k limit. OpenGL has way -too many GRATUITOUSLY_LONG_CONSTANTS and glLongStudlyFunctionNames(); +too many '`GRATUITOUSLY_LONG_CONSTANTS`' and '`glLongStudlyFunctionNames();`'. Therefore, much of the obfuscation comes secondary to just reducing the code size to fit under the limit while still having some semblance of a demo. @@ -95,7 +98,7 @@ There are some interesting abuses scattered about. ### Usage -Try hitting the spacebar when the program is running. +Try hitting the space bar when the program is running. ### For Fun @@ -107,11 +110,13 @@ Many thanks to John Clemens for testing this on various machines for me. ### Errors you can get - 0 = no error - 1 = X problem - 2 = Can't open glx - 3 = Can't open 16bpp visual - 4 = can't open source file +- 0 = no error. +- 1 = +[X](https://en.wikipedia.org/wiki/X_Window_System_protocols_and_architecture) +problem. +- 2 = Can't open [glx](https://en.wikipedia.org/wiki/GLX). +- 3 = Can't open 16bpp visual. +- 4 = can't open source file. ## Copyright and CC BY-SA 4.0 License: diff --git a/2006/birken/README.md b/2006/birken/README.md index bd997c191..794838256 100644 --- a/2006/birken/README.md +++ b/2006/birken/README.md @@ -2,9 +2,9 @@ ## (Electronic Design Automation - Mechanical Abstract Machine Emulator) - Michael Birken - US - o__1 at hotmail dot com +Michael Birken +US + ## To build: @@ -20,7 +20,7 @@ make [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed a segfault in macOS with this entry. The problem was a missing `+1` for strlen() with -malloc(). Thank you Cody for your assistance! +malloc(). This prevented it from working. Thank you Cody for your assistance! ## Try: @@ -54,14 +54,15 @@ And for those who are still confused: ## Author's remarks: -If man is capable of creating tofu hotdogs (simulated meat), then why -not tofu circuitry (simulated circuits)? This program is my tribute to -the early computer pioneers like Konrad Zuse. It's an educational tool -designed to introduce students to digital circuit theory using -technology that was considered state of the art in the 1940's! To -enable you to fully understand the capabilities of this circuit -simulator, I have included a 55 page manual (info.pdf) in the info -portion of the entry submission. +If man is capable of creating [tofu](http://en.wikipedia.org/wiki/Tofu) [hot +dogs](https://en.wikipedia.org/wiki/Hot_dog) (simulated meat), then why not tofu +[circuitry](https://en.wikipedia.org/wiki/Electronic_circuit) (simulated +circuits)? This program is my tribute to the early computer pioneers like +[Konrad Zuse](https://en.wikipedia.org/wiki/Konrad_Zuse). It's an educational +tool designed to introduce students to digital circuit theory using technology +that was considered state of the art in the 1940s! To enable you to fully +understand the capabilities of this circuit simulator, I have included a 55 page +manual ([info.pdf](info.pdf)) in the info portion of the entry submission. The primary obfuscation is the data structure chosen for parsing the input file and for executing the simulation. Oh man... coding that diff --git a/2006/borsanyi/Makefile b/2006/borsanyi/Makefile index 838b5a763..872cbecfa 100644 --- a/2006/borsanyi/Makefile +++ b/2006/borsanyi/Makefile @@ -73,7 +73,7 @@ CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${OPT} # Libraries needed to build # -LIBS= +LIBS= -lpthread # C compiler to use # diff --git a/2006/borsanyi/README.md b/2006/borsanyi/README.md index d2c6f7fec..e46959d33 100644 --- a/2006/borsanyi/README.md +++ b/2006/borsanyi/README.md @@ -1,12 +1,8 @@ # Most Useful - Szabolcs Borsanyi - Department of Physics and Astronomy - University of Sussex - Brighton - East Sussex BN1 9QH - United Kingdom - s.borsanyi at sussex dot ac dot uk +Szabolcs Borsanyi +United Kingdom +s.borsanyi at sussex dot ac dot uk ## To build: @@ -14,6 +10,10 @@ make ``` +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed (the Makefile) +under some systems where the `lpthread` was not implicitly linked in. Thank you +Cody! + ## To run: ```sh @@ -46,24 +46,27 @@ anti-CAPTCHA tools. Most spam robots collect email addresses from the web sites of innocent people, like you. Conference organizers cannot disclose the participant's address to prevent malicious users from -grabbing them. One solution is to write as my_email _at_ address -_dot_ com. But robots are clever enough to sort that out. A +grabbing them. One solution is to write as `my_email _at_ address +_dot_ com`. But robots are clever enough to sort that out. A more sophisticated approach is to create an image file with the email address and put that on the web page. -This program creates a GIF image file from the address given -in the command line. To avoid complications with patent issues -the LZW compression feature is not used. A typical email address -is stored in less than 1-2 kilobytes. +This program creates a GIF image file from the address given in the command +line. To avoid complications with patent issues the [LZW +compression](https://en.wikipedia.org/wiki/Lempel-Ziv-Welch) feature is not +used. A typical email address is stored in less than 1-2 kilobytes. ### Usage: - $ gcc email.c -lpthread -o email - $ ./email my@email.address.com > email.gif - $ my_favourite_gif_viewer email.gif +```sh +make all +./borsanyi my@example.com > email.gif +my_favourite_gif_viewer email.gif +``` The address cannot be longer than 42 characters, and may consist of -the characters: a-z_A-Z0-9@.- +the characters: `a-z_A-Z0-9@.-`. + The program is (like email addresses are) case insensitive. ### Obfuscation: @@ -73,26 +76,27 @@ entry supports up to 25 cores. The odd names in the bottom part of the program do have a meaning, they are not there just for obfuscation. The preprocessor is used to keep the program small, in fact, everything is a macro. Are you familiar with -the GIF format? Studying this program will give you a (very -little) insight. +the GIF format? Studying this program will give you a (very) +little insight. ### Questions: After analyzing the source code, try to answer these questions: + 1. How can you add a further supported symbol? 2. Can you alter the look of the output characters? 3. What limits the number of input characters to 42? ### Portability: -The program uses posix threads (using the linker flag -lpthread). +The program uses posix threads (using the linker flag `-lpthread`). The program accepts email addresses not longer than 42 bytes -composed from letters, digits, and the @._- symbols. An address +composed from letters, digits, and the `@._-` symbols. An address not obeying these rules will cause undefined behaviour. The program is not expected to depend on endianness. The standard output is used for a binary output, which might cause problems. To avoid most caveats, the program does not output the octet -0x0a. The program assumes the use of ASCII. +`0x0a`. The program assumes the use of ASCII. ## Copyright and CC BY-SA 4.0 License: diff --git a/2006/grothe/README.md b/2006/grothe/README.md index 20a414d0f..26f18310b 100644 --- a/2006/grothe/README.md +++ b/2006/grothe/README.md @@ -1,9 +1,7 @@ -# Most Obfuscaed Audio +# Most Obfuscated Audio - Aaron Grothe - 2205 South 51st Street - Omaha, NE 68106 - US +Aaron Grothe +US ## To build: @@ -43,86 +41,105 @@ feature to this entry. :-) ## Selected Author's Comments: The program draws patterns on the screen that can be picked up by a -shortwave radio. It emulates the frequencies for an old fashion touch -tone phone, so old songs can be played by hitting 0-9,#, and *. +[shortwave radio](https://en.wikipedia.org/wiki/Shortwave_radio). It emulates +the frequencies for an old fashion touch tone phone, so old songs can be played +by hitting `0-9`,`#`, and `*`. To be able to run the program you need to determine the following -parameters +parameters: - carrier_freq - base frequency used to host music - pixelclock - refresh rate of the monitor - horizontal_total - total scan along the horizontal axis +``` + carrier_freq - base frequency used to host music + pixelclock - refresh rate of the monitor + horizontal_total - total scan along the horizontal axis +``` -If you have xvidtune installed you can get the pixelclock and -horizontal total with the following command +If you have `xvidtune` installed you can get the `pixelclock` and +`horizontal_total` with the following command - xvidtune -show | head -n 1 | - awk '{ print "pixelclock " $2 * 1000000 " horizontal_total = " $6 }' +```sh +xvidtune -show | head -n 1 | awk '{ print "pixelclock " $2 * 1000000 " horizontal_total = " $6 }' +``` -example from my laptops +Example from my laptops: - ./grothe 65000000 10000000 1344 < twinkle.txt +```sh +./grothe 65000000 10000000 1344 < twinkle.txt +``` Even if the user gets a setting off, the sound will usually be able to be -heard on AM at a multiple of the original frequency +heard on [AM](https://en.wikipedia.org/wiki/AM_broadcasting) at a multiple of +the original frequency. The core idea of using a machine to play music on AM radio goes all the -way back to the Altair computers and Timex Sinclair ZX-81s. +way back to the [Altair computers](https://en.wikipedia.org/wiki/Altair_8800) +and [Timex Sinclair ZX-81](https://en.wikipedia.org/wiki/ZX81)s. ### Several example songs -Olympic Fanfare - from antang@phakt.usc.edu - Tony +Olympic Fanfare - from `antang@phakt.usc.edu` - Tony: +``` 4-9-91231,2222-321123123-9-91231,2222-32112321 +``` -Twinkle Twinkle Little Star - from fsufunkyb@aol.com - Ben Schmidt +Twinkle Twinkle Little Star - from `fsufunkyb@aol.com` - Ben Schmidt: +``` 1199##9-6633221-9966332-9966332-1199#9-6633221- +``` -Generic Arabian Tune - from rdippold@qualcomm.com -Ron "Asbestos" Dippold +Generic Arabian Tune - from `rdippold@qualcomm.com` - Ron "Asbestos" Dippold: +``` 453,54,4569564459,9#95458,8987453 54 +``` Others can be found by doing a search for "touch tone phone songs". ### Obfuscations - Some numbers expressed in Octal, some in hex and some in decimal - "A foolish consistency is the hobgoblin of little minds" - - Ralph Waldo Emerson -- Funky scoping, looking at the nanosleep section and - XsetWindowAttributes declares local variables -- Algorithm is very weird, uses y dimension to draw carrier frequency - and x dimension to draw audio frequency, based on Erik Thiele's - Tempest for Eliza -- lack of #defines confuses many people :-) -- figuring out your pixelclock and horizontal total and which carrier - frequency to use can be an exercise in obfuscation for the user -- use of commas in various places, confuses most c code beautifiers + "A foolish consistency is the hobgoblin of little minds" - Ralph Waldo + Emerson. + +- Funky scoping, looking at the nanosleep section and `XsetWindowAttributes` +declares local variables. +- Algorithm is very weird, uses `y` dimension to draw carrier frequency + and `x` dimension to draw audio frequency, based on [Erik + Thiele](http://www.erikyyy.de)'s + [Tempest for Eliza](http://www.erikyyy.de/tempest/). +- lack of `#define`s confuses many people :-) +- figuring out your `pixelclock` and `horizontal_total` and which `carrier_freq` + to use can be an exercise in obfuscation for the user. +- use of commas in various places, confuses most C code beautifiers sometimes making the beautified code harder to read -- use of static to ensure initilization is EVIL and done in several +- use of `static` to ensure initialization is EVIL and done in several places -- uses static declarations & voids function returns we don't care about - making the code harder to read -- does sound using only X11 libs, no other libs required -- demonstrates tempest emissions in a fun/easy way -- follows good programming practices of actually setting exit codes and - giving usage when run with incorrect parameters +- uses `static` declarations & `void` function returns we don't care about + making the code harder to read. +- does sound using only [X11 libs](https://en.wikipedia.org/wiki/Xlib), no other +libs required. +- demonstrates tempest emissions in a fun/easy way. +- follows good programming practices of actually setting exit codes and giving +usage when run with incorrect parameters. ### References -Tempest for Eliza - Basis for Algorithms +[Tempest for Eliza - Basis for Algorithms](http://www.erikyyy.de/tempest/). -> +[Tempest +AM](https://web.archive.org/web/20070612152538if_/http://silcnet.org/priikone/programs/tempest-AM-1.0.tar.gz) +\- Another early program in this field. See +[here](https://web.archive.org/web/20070612152538/http://silcnet.org/priikone/programs.php?lang=en) +for a bit more information on the program (search for `Tempest-AM Radio Signal +Transmitter`). -Tempest AM - Another early program in this field +The paper +[Soft Tempest: Hidden Data Transmission Using Electromagnetic +Emanations](https://www.cl.cam.ac.uk/~mgk25/ih98-tempest.pdf) by Markus G. +Kuhn's and Ross J. Anderson's. -> - -Paper by Markus G. Kuhn's and Ross J. Anderson's, -"Soft Tempest: Hidden Data Transmission Using Electromagnetic Emanations" - -> ## Copyright and CC BY-SA 4.0 License: diff --git a/2006/hamre/README.md b/2006/hamre/README.md index 5978c5ee7..b108814ec 100644 --- a/2006/hamre/README.md +++ b/2006/hamre/README.md @@ -1,7 +1,7 @@ # Most Irrational - Steinar Hamre - Norway +Steinar Hamre +Norway ## To build: @@ -21,28 +21,40 @@ make ./hamre '-1+4/3*(2+1/(3/2*(7/2-7/3+1/6)))/2' ``` +### INABIAF - it's not a bug it's a feature! :-) + +This program will very likely crash or do something completely irrational :-) if you +don't supply it with an argument. + +As well supplying more arguments will possibly limit the number of nested +operators supported. + +Don't try dividing by 0 (zero). + ## Judges' remarks: An irrationally coded source presents rational things! -A rational person might want to attempt the irrational task +A rational person might want to attempt the +[irrational](https://rationalwiki.org/wiki/Rationality) task of supporting a new operator by way of an existing macro in the source. And can you determine which macro this is and understand the purpose of its arguments? ## Author's remarks: -This is a calculator for rational numbers. Believe it or not, that is -a useful tool to have around, and I haven't found a useful version, -much less an obfuscated one. +This is a calculator for [rational +numbers](https://en.wikipedia.org/wiki/Rational_number). Believe it or not, that +is a useful tool to have around, and I haven't found a useful version, much less +an obfuscated one. -It is rather feature complete as rational calculators go. The +It is rather feature complete as [rational calculators go. The supported operators are: `+`, `-` (binary and unary), `*`, `/` and `()`. Run it by supplying an expression as the first argument, and the normalized result will be written to stdout. ```sh -$ ./hamre '-1+4/3*(2+1/(3/2*(7/2-7/3+1/6)))/2' +./hamre '-1+4/3*(2+1/(3/2*(7/2-7/3+1/6)))/2' 2/3 ``` @@ -50,7 +62,7 @@ If you do not supply an argument, the calculator will crash. Other arguments are ignored. Supplying more arguments may further limit the number of nested operators supported. -Remember that 1/0 is not a rational number. You will not get any +Remember that `1/0` is not a rational number. You will not get any answer if you divide by zero. By default, only 31 nested levels of operators are supported. @@ -62,9 +74,9 @@ comes to understanding the source. The preprocessed source becomes rather verbose. IOCCC entries are often loaded with all kinds of hard-coded numbers. I -have restricted myself to mostly use sensible numbers (<= 7) as +have restricted myself to mostly use sensible numbers (`<= 7`) as smaller numbers are much easier to remember. Also the macros really -help hiding most of the uses of these numbers away. All macros and +help hide most of the uses of these numbers away. All macros and variables are easy-to-remember single character abbreviations, from some language, meaningful to the purpose(s) of the macro, I hope. diff --git a/2006/meyer/README.md b/2006/meyer/README.md index b44a09b47..88331cd4a 100644 --- a/2006/meyer/README.md +++ b/2006/meyer/README.md @@ -1,7 +1,7 @@ # Best Game - Raphael Meyer - US +Raphael Meyer +US ## To build: @@ -34,41 +34,46 @@ more text to fulfil the program's requirements. This entry turns a newspaper solitaire puzzle into a competition with the computer to be the last one moving. The object of this -source code is to determine the object of this source code! :-) +[source code](meyer.c) is to determine the object of this [source +code](meyer.c)! :-) ## Author's remarks: I wanted submit a fully object-oriented entry to show that object-orientated code: - 1. is ridiculously bloated - 2. is unreadable - 3. isn't WYWIWID (what you write is what it does) anymore +1. is ridiculously bloated. +2. is unreadable. +3. isn't '`WYWIWID`' ('what you write is what it does') anymore. But I just totally failed. No, I didn't fail in showing any of the points above. Before I even had the chance to prove any of these claims, (1) already brought me to my knees. The code got -so much bloated up, that I missed the size limit by a few hundred +so bloated up, that I missed the size limit by a few hundred bytes. Therefore, I broke the only rule in this contest, I think you shouldn't break in any case: Rule Nr 2, The size of ... The degree of claim (2) actually depends on the compiler. As I -_manually_ compiled it from [a generic object-oriented programming -language] to C, it didn't just end up unreadable, but awfully +_manually_ translated it from a generic object-oriented programming +language to C, it didn't just end up unreadable, but awfully messed up, i.e. obfuscated. -As it is already (pre)compiled to C, you could also call it an object- +As it is already (pre)translated to C, you could also call it an object- disoriented program. Comparing this program to a potential object-oriented implementation, -it is obvious, that object-oriented code isn't WYWIWID (what -you write is what it does). It may be tempting to think that +it is obvious, that object-oriented code isn't '`WYWIWID`' ('what +you write is what it does'). It may be tempting to think that +``` Object o; +``` might do something similar as +```c struct not_an_object o; +``` But this program reveals that it doesn't. Even worse, this program only reveals the tip of the iceberg, what kind of black magic is involved in @@ -77,43 +82,52 @@ a simple declaration of an object. A few things you can explore about object-orientation in this program include: - - constructors (invoked by the new operator) - - new operators (every class gets its own new operator at compile time) - - virtual method tables - (all the virtual method tables have been combined to a single vtable) - - runtime method binding - - inheritance and polymorphism +- constructors (invoked by the new operator). +- new operators (every class gets its own new operator at compile time). +- virtual method tables (all the virtual method tables have been combined to a +single [vtable](https://en.wikipedia.org/wiki/Virtual_method_table)). +- runtime method binding. +- +[inheritance](https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)) +and +[polymorphism](https://en.wikipedia.org/wiki/Polymorphism_(computer_science)). It is left as an exercise to the reader to find a corresponding implementation in a popular object-oriented programming language. ### Starting the game - ./meyer [SEED] +```sh +./meyer [SEED] +``` ### Gameplay -It is a sudoku based game. The goal of the game is to be able -to do the last valid 'move'. +It is a [sudoku](https://en.wikipedia.org/wiki/Sudoku) based game. The goal of +the game is to be able to do the last valid 'move'. On your turn you have to set a free cell to a value between 1 to 9 without breaking the following rule. Any number must be unique in its: - 1. row - 2. column - 3. 3x3 block. +1. row +2. column +3. 3x3 block. Expected input for your move: - row column number +``` +row column number +``` where - row: [a-i] - column: [0-8] - number: [1-9]. +``` +row: [a-i] +column: [0-8] +number: [1-9]. +``` -The game can be aborted with 'q'. +The game can be aborted with `q`. The one who can do the last move wins the game. diff --git a/2006/monge/README.md b/2006/monge/README.md index 2905561f9..d88326249 100644 --- a/2006/monge/README.md +++ b/2006/monge/README.md @@ -1,15 +1,11 @@ # Best Compiled Graphics - Maurizio Monge - Department of Mathematics - University of Pisa - Pisa - Italy - maurizio.monge at gmail dot com +Maurizio Monge +Italy + ## To build: - Make sure you have the SDL1 (not SDL2!) development environment installed. ```sh @@ -37,11 +33,16 @@ it segfaulted on his MacBook Pro with the M1 chip). ./monge "z = 0" "z = z*z*z + c; Abs2(z) < 4" ``` +### INABIAF - it's not a bug it's a feature! :-) + +Incorrect formulas will ungracefully crash the program. + ## Judges' remarks: -For those who are familiar with the previous IOCCC winners, this program -is best described as "1994/tvr meets 2001/bellard". Here you have -mouse-manipulated fractals AND generated binary code, all in one package. +For those who are familiar with the previous [IOCCC winners](/winners.html), +this program is best described as "[1994/tvr](/1994/tvr/tvr.c) meets +[2001/bellard](/2001/bellard/bellard.c)". Here you have mouse-manipulated +fractals AND generated binary code, all in one package. A more appropriate award could have been "Best abuse of the rules", because on a non-x86-based architecture this program @@ -49,7 +50,7 @@ is, quite predictably, a dud. At the time of judging we were too mesmerized by the graphics to realize it; and, after all, this entry does take a special -effort to work on both i386 and x86_64. Portable it is! :) +effort to work on both `i386` and `x86_64`. Portable it is! :) ## Author's remarks: @@ -63,103 +64,103 @@ effort to work on both i386 and x86_64. Portable it is! :) ./monge "z = 0" "z = z*z + c; Abs2(z) < 4" -2. Keep clicked with left or right button to zoom in or out. +2. Keep clicking with left or right button to zoom in or out. -3. Use the number pad '+' and '-' to increase/decrease the iteration - count when needed. +3. Use the number pad `+` and `-` to increase/decrease the iteration count when +needed. -4. Enjoy, unless you're more interested in trying to understand - how it works. :) +4. Enjoy, unless you're more interested in trying to understand how it works. :) ### Introduction -This is a fractal generator that supports custom formulas and -real time zoom. The program needs to be run with two arguments, -the first being a semicolon separated list of assignments to -do once per pixel, and the second a semicolon separated list -of assignments and conditions that will be executed (and conditions -checked) for each iteration (up to the maximum). Using the -left and right mouse buttons you will be able to zoom in and -out (a la Xaos), the zooming algorithm is a bit slower than -Xaos's but it should give slightly better results. +This is a fractal generator that supports custom formulas and real time zoom. +The program needs to be run with two arguments, the first being a semicolon +separated list of assignments to do once per pixel, and the second a semicolon +separated list of assignments and conditions that will be executed (and +conditions checked) for each iteration (up to the maximum). Using the left and +right mouse buttons you will be able to zoom in and out (a la +[XaoS](https://github.com/xaos-project/XaoS)), the zooming algorithm is a bit +slower than `XaoS`'s but it should give slightly better results. -Formulas can use all a-z (lowercase) variables, and the special -variables 'c' and 'i' are respectively set by default to the -complex coordinate of the pixel and to the complex imaginary 'i'. +Formulas can use all `a-z` (lowercase) variables, and the special +variables `c` and `i` are respectively set by default to the +complex coordinate of the pixel and to the complex imaginary `i`. -All the constant numbers will be interpreted as real double -values. Each expression must be an assignment ([variable] = -[expr]) or a comparison with < or > ([expr1] < or > [expr2]), -and you can add spaces as you like (as understood by the c -function 'isspace'). +All the constant numbers will be interpreted as real double values. Each +expression must be an assignment (`[variable] = [expr]`) or a comparison with +`<` or `>` (`[expr1] < [expr2]` or `[expr1] > [expr2]`), and you can add spaces +as you like (as understood by the C function `isspace()`). Supported operations and functions are: Operation | Description :-------- | :---------- -> `+,-,*,/` | Arithmetic operations, priority of `*`,`/` over `+,-` is respected. -> `<,>` | Compares the real parts of two complex numbers (the imaginary part is ignored). Any number of conditions is allowed, the iteration will just stop as soon as one of them fails. -> Abs2 | Calculates the squared norm, ie: `Abs2(a+b*i)` is `(a*a+b*b)+0*i` -> Re | Extract the real part, ie: `Re(a+b*i) is a+0*i` -> Im | Extract the imaginary part, ie: `Im(a+b*i) is b+0*i` -> Exp | Calculates the complex exponential, ie `Exp(a+b*i)` is -> `e^a*(cos(b)+sin(b)*i)` -> Ln | Calculates the principal value of the natural logarithm, ie -> `Ln(a+b*i)` is `ln(a*a+b*b)/2` + `atan(b/a)*i` +`+,-,*,/` | Arithmetic operations, priority of `*`,`/` over `+,-` is + respected. + | +`<,>` | Compares the real parts of two complex numbers (the imaginary part + | is ignored). Any number of conditions is allowed, the iteration + | will just stop as soon as one of them fails. +`Abs2` | Calculates the squared norm, i.e.: `Abs2(a+b*i)` is `(a*a+b*b)+0*i`. +`Re` | Extract the real part, i.e.: `Re(a+b*i)` is `a+0*i`. +`Im` | Extract the imaginary part, i.e.: `Im(a+b*i) is b+0*i`. +`Exp` | Calculates the complex exponential, i.e. `Exp(a+b*i)` is + | `e^a*(cos(b)+sin(b)*i)` +Ln | Calculates the principal value of the natural logarithm, i.e. + `Ln(a+b*i)` is `ln(a*a+b*b)/2` + `atan(b/a)*i` Here are a few examples of fractals you can draw: - Mandelbrot: - ./program "z=1" "z=z*z+c; Abs2(z)<4" + ./monge "z=1" "z=z*z+c; Abs2(z)<4" - Mandelbrot (return time variation): - ./program "z=c" "z=z*z+c; Abs2(z-c)>0.0001" + ./monge "z=c" "z=z*z+c; Abs2(z-c)>0.0001" - Julia, for `c=0.31+i*0.5`: - ./program "z=c; c=0.31+i*0.5" "z=z*z+c; Abs2(z)<4" + ./monge "z=c; c=0.31+i*0.5" "z=z*z+c; Abs2(z)<4" - Julia (return time variation), `for c=0.31+i*0.5`: - ./program "z=c; c=0.31+i*0.5" "z=z*z+c; Abs2(z-c)>0.0001" + ./monge "z=c; c=0.31+i*0.5" "z=z*z+c; Abs2(z-c)>0.0001" - Newton, for `x^3-1`: - ./program "z=c" "p=z; z=0.6666*z+0.3333/(z*z); Abs2(p-z) > 0.001" + ./monge "z=c" "p=z; z=0.6666*z+0.3333/(z*z); Abs2(p-z) > 0.001" - Newton-Mandelbrot: - ./program "z=0" "p=z; z=z-(z*z*z + (c-1)*z - c)/(3*z*z+c-1); Abs2(p-z) > 0.001" + ./monge "z=0" "p=z; z=z-(z*z*z + (c-1)*z - c)/(3*z*z+c-1); Abs2(p-z) > 0.001" - Phoenix, Mandelbrot version: - ./program "z=0; q=0" "t=z; z=z*z+Re(c)+Im(c)*q; q=t; Abs2(z)<4" + ./monge "z=0; q=0" "t=z; z=z*z+Re(c)+Im(c)*q; q=t; Abs2(z)<4" -- Phoenix, Julia version for `c=0.56667-i*0.5` +- Phoenix, Julia version for `c=0.56667-i*0.5`: - ./program "z=c; c=0.56667-i*0.5; q=0" "t=z; z=z*z+Re(c)+Im(c)*q; q=t; Abs2(z)<4" + ./monge "z=c; c=0.56667-i*0.5; q=0" "t=z; z=z*z+Re(c)+Im(c)*q; q=t; Abs2(z)<4" ### Compilation and portability This program will only work on x86 (with an x87 FPU) or x86_64 machines, -and requires the SDL library. +but it requires the SDL library. -Another system requirement is the mmap function (as `#define`d -at the beginning of the program). If it is not available the -macro M(a) will have to be replaced with a system dependent -function that allocates readable, writable *AND* executable -memory (it will not be possible to make this program run on -paranoid systems (like OpenBSD IIRC) do not allow rwx memory). +Another system requirement is the `mmap()` function (as `#define`d at the +beginning of the program). If it is not available the macro `M(a)` will have to +be replaced with a system dependent function that allocates readable, writable +*AND* executable memory (it will not be possible to make this program run on +paranoid systems (like OpenBSD IIRC) that do not allow `rwx` memory). However I was able to compile and make work the program under -Linux (Debian/x86 and OpenSuSE/x86_64) and under Cygwin/x86. A +Linux (Debian/x86 and openSUSE/x86_64) and under Cygwin/x86. A friend of mine was able to make it work under macOS too. If you want you can change the window width and height, or the default number of iterations (that one can be tweaked at runtime, anyway) by -changing the definitions of W, H and I at the beginning of the code. +changing the definitions of `W`, `H` and `I` at the beginning of the code. ### Caveats (I just a selected few of them!) @@ -187,25 +188,26 @@ of how all the program works to be worked out). This program is a formula parser that outputs machine code that calculates the formula and check the given conditions. The -machine code targets the x87 stack based FPU, and it is almost +machine code targets the x87 stack based +[FPU](https://en.wikipedia.org/wiki/Floating-point_unit), and it is almost identical for x86 and x86_64 (except for the comparison instructions, that have to be generated differently). The program keeps track of the FPU stack (the FPU has a cyclic stack of 8 registers) and will automatically swap to and from the -main memory when required (ie, adds instructions to the generated +main memory when required (i.e., adds instructions to the generated machine code to take care of this issue). The formulas are parsed recursively and machine code for the inner iteration loop is also generated. After generating the machine code, a big event loop creates (or -zooms into) the factal executing the generated code when needed, +zooms into) the fractal executing the generated code when needed, and then waits for input events. The zooming algorithm works by remembering for each pixel the floating point offset to where the value was actually calculated. When zooming, the best match is searched, and if the offset is -too big (>1) the pixel is recalculated. +too big (`>1`) the pixel is recalculated. ## Copyright and CC BY-SA 4.0 License: diff --git a/2006/night/.gitignore b/2006/night/.gitignore index 41feb5b6d..3ba331560 100644 --- a/2006/night/.gitignore +++ b/2006/night/.gitignore @@ -1 +1,2 @@ night +night.alt diff --git a/2006/night/Makefile b/2006/night/Makefile index bc828b900..17dc0fcc2 100644 --- a/2006/night/Makefile +++ b/2006/night/Makefile @@ -116,8 +116,8 @@ OBJ= ${PROG}.o DATA= TARGET= ${PROG} # -ALT_OBJ= -ALT_TARGET= +ALT_OBJ= ${PROG}.alt.o +ALT_TARGET= ${PROG}.alt ################# @@ -139,6 +139,9 @@ ${PROG}: ${PROG}.c alt: data ${ALT_TARGET} @${TRUE} +${PROG}.alt: ${PROG}.alt.c + ${CC} ${CFLAGS} $< -o $@ ${LIBS} + # data files # data: ${DATA} diff --git a/2006/night/README.md b/2006/night/README.md index aed239822..a2449c481 100644 --- a/2006/night/README.md +++ b/2006/night/README.md @@ -1,11 +1,8 @@ # Best Abuse of Computation - Christopher Night - Harvard University - Department of Astronomy - Cambrige MA 02238 - US - +Christopher Night +US + ## To build: @@ -19,18 +16,44 @@ make ./night ``` +There is an alternate version that supports arrow keys. See the alternate code +section below. + ## Try: ```sh echo "Do or do not. There is no try." ``` +### Alternate code: + +As [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) is a lost :-) `vim` +user he took the author's remarks to add support back for arrow keys. To use +compile like: + + +```sh +make alt +``` + +Use `night.alt` as you would `night` above. + +Thank you Cody! + + ## Judges' remarks: -You'd never guess, from looking at the code, that there is a -genetic algorithm involved. Somewhere. But what does it do? -Well, it might take you a while to navigate the results, let -alone the code. +You'd never guess, from looking at the code, that there is a [genetic +algorithm](https://towardsdatascience.com/introduction-to-genetic-algorithms-including-example-code-e396e98d8bf3) +involved. Somewhere. But what does it do? Well, it might take you a while to +navigate the results, let alone the code. + +### Cheating + +There is a nice way to cheat. If you don't want to figure it out you can look at +[Yusuke Endoh](/winners.html#Yusuke_Endoh)'s analysis of this entry at +(translation from Japanese so it's not perfect) +. ## Author's remarks: @@ -42,29 +65,28 @@ Oh, wait a second... it is a maze-generating program. Oops! ### What it does: -This program solves an optimization problem, namely, generating a -challenging maze. It uses a very simple genetic algorithm: a maze -layout's DNA is represented as a 32-bit integer, and mutations consist -of flipping three different bits. The algorithm is simple in that it -doesn't employ sexual reproduction, only mutations, and it has a +This program solves an optimization problem, namely, generating a challenging +maze. It uses a very simple genetic algorithm: a maze layout's +[DNA](https://en.wikipedia.org/wiki/DNA) is represented as a 32-bit integer, and +mutations consist of flipping three different bits. The algorithm is simple in +that it doesn't employ sexual reproduction, only mutations, and it has a population size of 1. So much for diversity! This particular optimization problem, I believe, has a unique maximum: -there is but one maze out of 2^32 that requires 64 moves to solve. The +there is but one maze out of `2^32` that requires 64 moves to solve. The program will run until finding this global maximum, or if you get bored, you can accept a sub-optimal solution by pressing any key. On my system, it takes an average of 15 minutes to find the maximum, whereas a random search would take an average of 3.5 days. -Should you take my word for it that the maze it generates requires as -many moves as I say it does? The answer is yes. But if you're not -convinced, you can try to solve it yourself. The goal is to traverse -from the upper-left to the upper-right and out the top, where the -number of moves remaining is printed. Use the arrow keys for suckers -(w, a, s, d) to move around. q quits and r restarts. Also, the maze -changes as you move through it, in a predictable way. It should be -easy enough to figure out the pattern. For best results, use a display -with bold-text capabilities and color. +Should you take my word for it that the maze it generates requires as many moves +as I say it does? The answer is yes. But if you're not convinced, you can try to +solve it yourself. The goal is to traverse from the upper-left to the +upper-right and out the top, where the number of moves remaining is printed. Use +the arrow keys for suckers (`w`, `a`, `s`, `d`) to move around. `q` quits and +`r` restarts. Also, the maze changes as you move through it, in a predictable +way. It should be easy enough to figure out the pattern. For best results, use a +display with bold-text capabilities and color. Finally, in the world of DNA, the medium is truly the message. There's a short message encoded in here that will only appear when you @@ -76,37 +98,37 @@ These depend on your compiler, and they were all intentionally added for obfuscation purposes. No, really! My compiler warns of nulls in a string literal, and the redefinition -of the macro T. +of the macro `T`. On one compiler, compilation took about two minutes. `sizeof(unsigned short)` must be 2, and `sizeof(unsigned long)` must be 4. -CLOCKS_PER_SEC is assumed to be 1000000. If it's a lot less than that, +`CLOCKS_PER_SEC` is assumed to be `1000000`. If it's a lot less than that, expect delays. ### Algorithmic obfuscation: The representation of the maze layout in a 32-bit integer type is pretty opaque. As a hint, the optimum layout's DNA is, in base 4, -2102231031201230. Try getting from there to the maze that appears on +`2102231031201230`. Try getting from there to the maze that appears on screen. -The recursive function CGAC replaces a nested for loop in a handy way. +The recursive function `CGAC()` replaces a nested for loop in a handy way. -The maze-solving function TGA returns no solution both if no solution +The maze-solving function `TGA()` returns no solution both if no solution exists, and if the search space grows too large, with a single test. ### Stylistic obfuscation: -Four-letter alphabets are confusing. I don't know how ribosomes -manage. +Four-letter alphabets are confusing. I don't know how +[ribosomes](https://en.wikipedia.org/wiki/Ribosome) manage. -Overloaded symbols, such as G and G(). +Overloaded symbols, such as `G` and `G()`. -Who needs != when you've got ^? +Who needs `!=` when you've got `^`? -Who needs if when you've got while? +Who needs `if` when you've got `while`? For that matter, who needs fixed-iteration-count for and while when you can just duplicate code with the preprocessor? Duplication by this @@ -117,8 +139,10 @@ hindering the preprocessor's ability to deobfuscate. Keypad support was removed to save space. To restore, modify the following two macros to: +```c #define ATG srand(time(0)); initscr(); cbreak(); noecho(); start_color(); keypad(stdscr,1); #define AGG A&2?KEY_UP:KEY_DOWN:A&1?KEY_RIGHT:KEY_LEFT +``` Code on! diff --git a/2006/night/night.alt.c b/2006/night/night.alt.c new file mode 100644 index 000000000..fb67011e5 Binary files /dev/null and b/2006/night/night.alt.c differ diff --git a/2006/sloane/.gitignore b/2006/sloane/.gitignore index 84c5a1b15..8beae2eb9 100644 --- a/2006/sloane/.gitignore +++ b/2006/sloane/.gitignore @@ -1 +1,2 @@ sloane +sloane.alt diff --git a/2006/sloane/Makefile b/2006/sloane/Makefile index 32d78712a..d4bf0b5b8 100644 --- a/2006/sloane/Makefile +++ b/2006/sloane/Makefile @@ -58,11 +58,11 @@ ARCH= # Defines that are needed to compile # -CDEFINE= +CDEFINE= -DZ=65000 # Include files that are needed to compile # -CINCLUDE= +CINCLUDE= -include math.h -include stdio.h # Optimization # @@ -74,7 +74,7 @@ CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${OPT} # Libraries needed to build # -LIBS= +LIBS= -lm # C compiler to use # @@ -115,8 +115,8 @@ OBJ= ${PROG}.o DATA= TARGET= ${PROG} # -ALT_OBJ= -ALT_TARGET= +ALT_OBJ= ${PROG}.alt.o +ALT_TARGET= ${PROG}.alt ################# @@ -138,6 +138,9 @@ ${PROG}: ${PROG}.c alt: data ${ALT_TARGET} @${TRUE} +${PROG}.alt: ${PROG}.alt.c + ${CC} ${CFLAGS} $< -o $@ ${LIBS} + # data files # data: ${DATA} diff --git a/2006/sloane/README.md b/2006/sloane/README.md index b4a20c5e3..061e77b17 100644 --- a/2006/sloane/README.md +++ b/2006/sloane/README.md @@ -1,9 +1,7 @@ # Homer's Favorite - Andy Sloane - 1041 Seneca St. - Hartford, WI 53027 - US +Andy Sloane +US ## To build: @@ -15,7 +13,10 @@ make work with clang which is stricter on the type of args to main(). Curiously although clang requires the types of args to be strictly correct it allows for only one arg which he made it as the second arg was not used and this allows for -a closer match to the original format of the entry. Thank you Cody for your +a closer match to the original format of the entry. He also made sure that the +Makefile links in `libm` as not all systems do this by default. Since the author +suggested that the lack of certain `#include`s might break the program in some +systems he added `-include ...` to the Makefile as well. Thank you Cody for your assistance! @@ -28,6 +29,10 @@ assistance! WARNING: if you are easily overstimulated with fast movement or have photosensitivity please be careful running this entry! +An alternatively version of this entry exists so that one can actually see what +is going on. This is also more ideal for those who are overstimulated by fast +movements. See the alternate code section below. + ## Try: @@ -35,6 +40,30 @@ photosensitivity please be careful running this entry! echo "Do or do not. There is no try." ``` +### Alternate code: + +The alternate version, provided by [Cody Boone +Ferguson](/winners.html#Cody_Boone_Ferguson), uses `usleep()` so one can enjoy +the entry with modern systems and which will not be too stimulating for those +who have a problem with fast moving text (like himself). It uses the `Z` macro +as the parameter to `usleep()` which you can override. The default is +`-DZ=65000`. To compile with the default: + + +```sh +make alt +``` + +If you wish to override the sleep value try something like: + +```sh +make CDEFINE="-DZ=70000" clobber alt +``` + +Use `sloane.alt` as you would `sloane` above. + +Thank you Cody! + ## Judges' Comments: Looks almost good enough to eat, dunnit? I suppose you could argue that, @@ -43,13 +72,14 @@ at first blush, this looks like a self-reproducing program. ## Author's remarks: This program doesn't require any special build options, other than that it -uses sin and cos and hence requires the math library. +uses `sin()` and `cos()` and hence requires the math library. You will almost certainly get a compiler warning because I declared a bunch of global ints without types. The code looks better this way, though, I -think. There are also no #includes, so there may be warnings for -undeclared references to printf, etc. There's a chance that my failure to -include math.h or declare sin or cos will make the donut not render +think. There are also no `#include`s, so there may be warnings for +undeclared references to `printf()`, etc. There's a chance that my failure to +include `math.h` or declare `sin()` or `cos()` will make the +[donut](https://en.wikipedia.org/wiki/Doughnut) not render properly -- it's worked on every system I've tried so far though. You will need some kind of VT100-ish emulation; so while this compiles and @@ -59,12 +89,11 @@ The shape of the source gives a hint about its output: it's a little animation of a shaded donut rotating over an infinite checkerboard. Like many IOCCC entries, it is thus self-documenting. -I wanted to create something as "pure" as I could - meaning that the -entire source code is shaped into a work of art, without being prefixed -by any #define hacks, or even #includes, _and_ is portable enough to not -require any special libraries to do the animating. I achieved this with -two standard escape codes for clearing the screen and moving the cursor -back to the top-left. +I wanted to create something as "pure" as I could - meaning that the entire +source code is shaped into a work of art, without being prefixed by any +`#define` hacks, or even `#includes`, _and_ is portable enough to not require +any special libraries to do the animating. I achieved this with two standard +escape codes for clearing the screen and moving the cursor back to the top-left. The donut isn't raytraced. It's much simpler than that. diff --git a/2006/sloane/sloane.alt.c b/2006/sloane/sloane.alt.c new file mode 100644 index 000000000..3a0c6362f --- /dev/null +++ b/2006/sloane/sloane.alt.c @@ -0,0 +1,32 @@ +_,x,y,o ,N;char b[1920] ;p(n,c) +{for(;n --;x++) c==10?y +=80,x= +o-1:x>= 0?80>x? c !='~'?b +[y+x]=c :0: 0:0;}c( + q,l,r) char*l,*r;{while (q>=0)q + =("E" "?yYrIxC{e^}KhE>[|LXbj}" "dOVsJ" + "@" "idOV{Yab[bW}[bW}\\qFywyv{D" "ma\\A" + "" "Ztq?Lyw>e{|Zq>Y\\gq\\qI[tYBe{w" "yvDZE\ +vBA[`_" "Lo>}KcqdYrWqKxzKtW]|DXRwsfcUaT\\\ +KXw{Y" "RsFwsFwsFw{zaqyaz|FmMpyaoyI\\]cuUw{J" +[_/6] -62>>_++%6&1?r[q]:l[q])-99;return q;}E(a +){for (o=x=a,y=0,_=0;_ <1006;)a=" /\\\n" + "~|_."[c(6,"b" "cd\\a[g","^`" "_e" + "]fh")+8], p( "#$%" "&'()*+,-.1"[ c(11 + ,"_ac[]\\YZi" "jkm", "`bd^efghXWlV" )+13 + ]-34,a);}main (k ){ float z[1920] ,A=0 +,B=0 ,i,j; puts("" "\x1b" "[2J");for(;; +) { float e=sin(A ), n= sin(B),g=cos( +A),m =cos(B);for(k =0;k< 1840;k++)y=-k +/80- 10,o=41+(k%80- 40)*1.3/y+n,N= + A-100.0/y, b[k]= ".#"[o+N&1],z[k] =0;E( + 80-(int)(9*B)%250);for(j=0;6.28>j;j+=0.07 )for( + i=0;6.28>i;i+=0.02) { float c=sin(i),d =cos(j + ),f=sin(j),h=d+2,D=15/(c*h*e+f*g+5 ),l=cos +(i),t=c *h*g-f*e;x=40+2*D*(l*h*m-t*n),y= 12 ++D*(l*h *n+t*m),o=x+80*y,N=8*((f*e-c *d* +g)*m-c* d*e-f*g-l*d*n);if(D>z[o] )z[o] +=D,b[o] =" ..,,-++=#$@"[ N>0?N:0 + ] ; } printf( + "\x1b[" "H" );usleep(Z);for(k =1;1841 + >k;k++) putchar (k%80?b [k]:10) + ; A += 0.053;B +=0.037 ; } } diff --git a/2006/stewart/.gitignore b/2006/stewart/.gitignore index 37f39acaa..d5e9679a5 100644 --- a/2006/stewart/.gitignore +++ b/2006/stewart/.gitignore @@ -1,2 +1,4 @@ stewart stewart.html +maze.xbm +maze.png diff --git a/2006/stewart/README.md b/2006/stewart/README.md index 385d8a479..22c86271b 100644 --- a/2006/stewart/README.md +++ b/2006/stewart/README.md @@ -1,7 +1,7 @@ # Best Computed Graphics - Thomas Stewart - US +Thomas Stewart +US ## To build: @@ -12,16 +12,22 @@ make ## To run: ```sh -./stewart +./stewart width_and_height iterations file > file.xbm +convert file.xbm file.png ``` +NOTE: you cannot specify a different width from height; it's one number. + +NOTE: `convert(1)` belongs to [ImageMagick](https://imagemagick.org/index.php). + ## Try: ```sh -./stewart 640 480 FILE +./stewart 400 1000000 maze > maze.xbm +convert maze.xbm maze.png ``` -where FILE is one of: +where `FILE` is one of: altar box box2 box3 build carpet circles cross cross2 cross3 crystal curve diamonds diamonds2 dragon dragon2 dragon3 @@ -29,9 +35,15 @@ where FILE is one of: pentagon pentagons rings rings2 spirals spirals2 spirals3 spirals4 squares stars stars2 tree tree2 tree3 tree4 triangle + +### INABIAF - it's not a bug it's a feature! :-) + +This program will very likely crash or do something funny if the file does not +exist or cannot be opened. + ## Judges' remarks: -Note the interesting choice of using a #define in the output. +Note the interesting choice of using a `#define` in the output. The selection of input files makes this one endlessly fun to play with. Many image viewers will be able to read the results, as will a reasonably experienced user who can parse formats in their mind. :-) @@ -42,45 +54,52 @@ a reasonably experienced user who can parse formats in their mind. :-) The program should be run with the following - prog +``` + ./stewart m = The size of the picture (picture will be m X m in size). n = The number of iterations to run (More will make for a clearer picture). ifs = The file to use as input. +``` -The program will spit out a xbm image on standard out. +The program will spit out a [XBM image](https://en.wikipedia.org/wiki/X_BitMap) on standard out. Minimal checking is done on the arguments mainly that there are 3. Wrong arguments will cause the program to bomb out. Ex: - ./stewart 1024 1000000 gasket > gasket.xbm +```sh +./stewart 1024 1000000 gasket > gasket.xbm +``` ### Compilation/Testing -The program compiles without warning with gcc -ansi -Wall. -lint also seems to like the code. This must be a bug in lint. +The program compiles without warning with `gcc -ansi -Wall`. +`lint` also seems to like the code. This must be a bug in lint. The program was tested on Linux on a x86 and NetBSD on an alpha. -Only gcc was tested for compilers (4.0.3 and 3.3.3) +Only gcc was tested for compilers (4.0.3 and 3.3.3). ### Entry originality -In looking through past winners. THere seem to be only 2 (92 and 94) -that generated fractals. Both of those were Julia fractals from the -Mandlebrot set. Those do make for some pretty pictures. I figured -it would be nice to add some more fractals to the IOCCC, since one -hasn't won since 1994. +In looking through past winners, there seem to be only 2 (92 and 94) that +generated fractals. Both of those were [Julia +fractals](https://en.wikipedia.org/wiki/Julia_set) from the [Mandelbrot +set](https://en.wikipedia.org/wiki/Mandelbrot_set). Those do make for some +pretty pictures. I figured it would be nice to add some more fractals to the +IOCCC, since one hasn't won since 1994. Instead of something that has already won I figured I would go with -another kind of fractal, those from the Iterated Function System (IFS). +another kind of fractal, those from the [Iterated Function System +(IFS)](https://en.wikipedia.org/wiki/Iterated_function_system). ### Input File The format of the input file is as follows: +```

@@ -88,85 +107,95 @@ The format of the input file is as follows: . . . +``` This file describe an IFS. -One of the most well known would be the Sierpinski Gasket: +One of the most well known would be the [Sierpinski Gasket](gasket): +``` 3 0 0 1 1 .5 0 0 .5 0 0 .33 .5 0 0 .5 .5 0 .33 .5 0 0 .5 .25 .433 .34 +``` -or the fern: +or the [fern](fern): +``` 4 -5.5 0 5.5 11 0 0 0 .16 0 0 .01 .85 .04 -.04 .85 0 1.6 .85 .2 -.26 .23 .22 0 1.6 .07 -.15 .28 .26 .24 0 .44 .07 +``` etc... -Included in my submission will be a tar ball of some ifs files, +Included in my submission will be a tarball of some IFS files, including one that attempts (not very well) to mimic the IOCCC logo -(I figure it can't hurt to attempt to suck up, right?) +(I figure it can't hurt to attempt to suck up, right?). I would try to explain how to create an IFS file but I am not smart enough to condense it down to something that is coherent. Basically the break down is: -num is the number of equations in the IFS. -x (min, max) and y (min, max) define the ranges that will be displayed -in the xbm. -The a b c d e f are used to iterative find points that lie in the IFS +`num` is the number of equations in the `IFS`. +`x` (min, max) and `y` (min, max) define the ranges that will be displayed +in the `xbm`. + +The `a b c d e f` are used to iterative find points that lie in the `IFS` from the algorithm - x = a * prevx + b * prevy + e; - y = c * prevx + d * prevy + f; +``` +x = a * prevx + b * prevy + e; +y = c * prevx + d * prevy + f; +``` -The p is for the probability that the equation will run. +The `p` is for the probability that the equation will run. ### Obfuscations -The main obfuscation is using a void* as my only variable (aside from -the args for main). This causes me to do much casting and porinter +The main obfuscation is using a `void *` as my only variable (aside from +the args for `main()`). This causes me to do much casting and pointer arithmetic to get the correct location and completely does away with any meaning the variables could have. This also makes the code more -convientient to read in the current form vs preprocessed. After +convenient to read in the current form vs preprocessed. After preprocessing there will almost be 300 casts in the code and I believe they are all needed... (I would double check but my brain is kinda mushy right now from chasing down a segfault in the code.) -The other main obfuscation being that it generates an IFS. Which isn't +The other main obfuscation being that it generates an `IFS`. Which isn't all that common for a program to do. I mean google only has something like 66,000 hits for "Iterated function system" so that means it is obscure, right? -Some other minor obfuscations: +### Some other minor obfuscations + Since I formatted it as a "normal" program I did inject something that on first glance will looks like a possible bug. (When you run it through -a c-beautifier this will be removed.) +a C-beautifier this will be removed.) -I decided not to use rand() to generate a pseudo random number. Instead -I use xor and bit shifting. +I decided not to use `rand()` to generate a pseudo-random number. Instead +I use XOR and bit shifting. The input file is used to make the program flexible and to allow it to -generate many different IFSs. This has the added bonus of hiding +generate many different `IFS`s. This has the added bonus of hiding information about the algorithm. The use of many magic numbers. I figured if I get yelled about them in a review they must be bad, right? -Silly things: -The use of decimal numbers where one would expect hex. Octal numbers -where one would expect decimal. Shifts instead of devides. +### Silly things -Using xbm as the output format. This might confuse someone who doesn't +The use of decimal numbers where one would expect hex. Octal numbers +where one would expect decimal. Shifts instead of divides. + +Using `xbm` as the output format. This might confuse someone who doesn't have an X background. It happens to be easy but is probably a very bad -choice from a filesize standpoint. 1024x1024 image is 641k in size. +choice from a file size standpoint. 1024x1024 image is 641k in size. ## Copyright and CC BY-SA 4.0 License: diff --git a/2006/sykes1/README.md b/2006/sykes1/README.md index a83b10414..1dbc82ca7 100644 --- a/2006/sykes1/README.md +++ b/2006/sykes1/README.md @@ -1,10 +1,8 @@ # Best Assembler - Stephen Sykes - Itäinen koulupolku - Kauniainen - Finland - +Stephen Sykes +Finland + ## To build: @@ -28,29 +26,56 @@ Next point your browser to the file: `sykes1.html`. Refresh your browser. +### Also try: + +If you have all day :-) and wish to find out how fast your machine can solve the +maximum: + + +```sh +time ./sykes1 19186 +``` + +This was done on a CentOS 7 server with `Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz` +with 16 cores (via HyperThreading): + + real 7m48.287s + user 7m48.223s + sys 0m0.004s + +and done with macOS Ventura with the Max M1 chip: + + real 8m26.466s + user 8m23.134s + sys 0m2.981s + + ## Judges' remarks: -Read the sykes1.html page source. -Now then read the C source. Confused? :-) +Read the [sykes1.html](sykes1.html) page source. +Now then read the C source. Confused? :-) If it's not clear try: + +```sh +diff -s sykes1.c sykes1.html +``` For extra credit, understand what happens when you give this entry an negative number argument, and why. +See the author's remarks for how to make your own shapes as well. + ## Author's remarks: -This cube shaped program solves the fiendishly difficult "Bedlam Cube" +This cube shaped program solves the fiendishly difficult "Bedlam Cube". -If you did not get one for Christmas, there is an article about these -puzzles in wikipedia: +If you did not get one for Christmas, there is an [article about these +puzzles in wikipedia](http://en.wikipedia.org/wiki/Bedlam_cube). -> +Some instructions on how to make your own cube are in the included file +[bedlam-cubes.pdf](bedlam-cubes.pdf). -There is also website dedicated to them - -And some instructions on how to make your own cube here: - -Finally, you can watch it being solved here: - -> +Finally, you can watch it being solved +[here](https://www.youtube.com/watch?v=a8s1AcYMLBc). Actually the cube is very hard to do by hand by just trying to fit it together. I have not known anyone to solve it in this way - you would @@ -66,13 +91,13 @@ Compile the program, then test that it works: Shortly you should see the first solution pop out on your screen. It shows you how to build the cube piece by piece, rendered in glorious -3d ascii. +3D ASCII. -Ascii art is all very well, but you also have a web browser, right? -Well, just open the file sykes1.html. This html file is just a copy -of prog.c, which helpfully contains an html document that should make -the browser display for you a nice animated gif, showing you how to -build the cube. Rendered in glorious 3d color. +ASCII art is all very well, but you also have a web browser, right? Well, just +open the file [sykes1.html](sykes1.html). This html file is just a copy of +[sykes1.c](sykes1.c), which helpfully contains an html document that should make +the browser display for you a nice animated GIF, showing you how to build the +cube. Rendered in glorious 3D color. Want to see another solution? Try: @@ -83,7 +108,7 @@ Want to see another solution? Try: The program will discard solutions up to the number, and output numbered solution. Refresh your browser window to see the new solution. -Try some more - there are exactly 19186 solutions to choose from. +Try some more - there are exactly `19186` solutions to choose from. If you have a fast machine you might try the last solution: @@ -107,16 +132,19 @@ int s[ ] = { 186, 94, 1426, 3098 Each piece is a bitmap, and represents a 3x3x3 cube. -For instance the first piece is 186 - this is 010111010 in binary. +For instance the first piece is `186` - this is `010111010` in binary. Written out like this you can see that it is the cross shaped piece: +``` 010 111 010 +``` The other pieces are defined similarly. Most of the rest require more -than one layer, such as piece 3 (1426): +than one layer, such as piece 3 (`1426`): +``` 000 000 010 @@ -124,10 +152,12 @@ than one layer, such as piece 3 (1426): 110 010 010 +``` Imagine the two layers on top of each other, and you should see this shape: +``` +---------+ / +----+ /| +-/ /| / | @@ -138,6 +168,9 @@ shape: | | / | |/ +----+ +``` + +### Making your own shapes The program is in fact a general solver - you can change the shape of the pieces, and provided that a solution is possible, it will be found. @@ -158,7 +191,7 @@ of the pieces. Once those placings are ready, the program recursively checks each combination thereof. -In order to complete in a reasonable time, care is take to eliminate +In order to complete in a reasonable time, care is taken to eliminate any branches that cannot result in a solution. This is done by checking after each placing if all the remaining pieces can be placed somewhere, and that all the free space in the cube can be filled by at least one @@ -166,49 +199,49 @@ viable placing. Also if a piece is found to only have one possible placing, it is placed immediately without invoking a recursive function call. -Once the solution is found, the ascii and gif representations are +Once the solution is found, the ASCII and GIF representations are generated. Care must be taken to render cubes in the right order such that pieces further back are occluded by those in front. -In the ascii output care must be taken with drawing the edges of each -1/64th cube (edges must be removed within each piece). In the gif +In the ASCII output care must be taken with drawing the edges of each +`1/64th` cube (edges must be removed within each piece). In the GIF this is taken care of by color, which is graded from the back to the front to ensure edge visibility. ### Notes -The whole program has just one function - main - which is recursively +The whole program has just one function - `main()` - which is recursively called. In fact if you select solution 19186 it will be called exactly -159,260,759 times. +`159,260,759` times. -If you pick a number higher than 19186, the program will return a -solution but it will be a rotation of one of the first 19186. This is +If you pick a number higher than `19186`, the program will return a +solution but it will be a rotation of one of the first `19186`. This is because the cross shaped piece fits 48 ways in the 4x4 cube, but only 2 of those ways are unique - you can rotate one of those to make any of the other 46. The algorithm used always places the cross piece -first, so the first two placings of that piece result in the 19186 +first, so the first two placings of that piece result in the `19186` unique solutions. -If you pick a number higher than 460464 (24x19186) the program will +If you pick a number higher than `460464` (`24x19186`) the program will return without outputting a solution. If you can wait that long. I recommend compiling with the most aggressive optimization options -your compiler supports. I find --unroll-loops to be helpful with gcc. +your compiler supports. I find `--unroll-loops` to be helpful with gcc. -The program relies on long long being 64 bits, but has no other special +The program relies on `long long int` being 64 bits, but has no other special requirements. -The program is known to compile and run under gcc and intel cc, as well +The program is known to compile and run under gcc and Intel cc, as well as PellesC on Windows. ### Bugs The program is not at all a valid html document, but fortunately browsers have good error recovery and amongst other things will ignore -the /* at the beginning, and won't mind the missing html and head tags +the `/*` at the beginning, and won't mind the missing html and head tags and the lack of end tags. -The generated gif is not compressed. This could be argued as an +The generated GIF is not compressed. This could be argued as an advantage - at least I don't violate any of those old Unisys patents! The pieces aren't really those colors. Unless you make your own. diff --git a/2006/sykes1/bedlam-cubes.pdf b/2006/sykes1/bedlam-cubes.pdf new file mode 100644 index 000000000..4c0166100 Binary files /dev/null and b/2006/sykes1/bedlam-cubes.pdf differ diff --git a/2006/sykes2/README.md b/2006/sykes2/README.md index 4f04fbb13..f0f22970e 100644 --- a/2006/sykes2/README.md +++ b/2006/sykes2/README.md @@ -1,10 +1,8 @@ # Best One Liner - Stephen Sykes - Itäinen koulupolku - Kauniainen - Finland - +Stephen Sykes +Finland + ## To build: @@ -15,26 +13,23 @@ make ## To run: ```sh -./prog +./sykes2 ``` ## Try: ```sh -while :; do - clear - rm -f sykes2 - make sykes2 - ./sykes2 - sleep 1 -done +./sykes2.sh ``` +This will repeatedly remake the program and run it then sleep for one second for +a nice show of time. + ## Judges' Comments: As they say, "Lather, rinse, repeat"! :-) -If you have the time, figure out how this small 1-line entry works! +If you have the time :-), figure out how this small 1-line entry works! ## Author's remarks: @@ -45,16 +40,15 @@ The clock numerals are rendered as an old fashioned 7 segment display. The encodings for which segments light for which number, and for where each segment appears on screen are hidden in the two strings. -When reading the program, you may want to refer to a table of -operator precedence - careful choices were made to keep the usage of -brackets to a minimum, and to keep the character count as low as -possible. +When reading the program, you may want to refer to a table of operator +precedence (try `man 7 operator`) - careful choices were made to keep the usage +of brackets to a minimum, and to keep the character count as low as possible. One interesting bit of obfuscation - the null at the end of the second string actually forms part of the lookup table. -Intel CC warns about the lack of a declaration for the argument to main. -(gcc does not notice this though, even with -Wall.) But anyway it can +Intel CC warns about the lack of a declaration for the argument to `main()`. +(`gcc` does not notice this though, even with `-Wall`.) But anyway it can easily be declared as int at the expense of 4 more characters. I'm not sure of the effects on a hard disk of rewriting the same file diff --git a/2006/sykes2/sykes2.sh b/2006/sykes2/sykes2.sh new file mode 100755 index 000000000..51f237072 --- /dev/null +++ b/2006/sykes2/sykes2.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +while :; do + clear + rm -f sykes2 + make sykes2 2>/dev/null 1>&2 + ./sykes2 + sleep 1 +done diff --git a/2006/toledo1/README.md b/2006/toledo1/README.md index c3bc3ced6..0877429d0 100644 --- a/2006/toledo1/README.md +++ b/2006/toledo1/README.md @@ -1,10 +1,9 @@ # Best Small Program - Oscar Toledo - Av. Santa Cruz del Monte 9-304 - Ciudad Satelite. Edo. de Mexico - CP. 53110 - Mexico +Oscar Toledo G. +Familia Toledo +Mexico + ## To build: @@ -15,9 +14,12 @@ make ## To run: ```sh -./toledo1 twodigits +./toledo1 [0-9][0-9] ``` +where `[0-9][0-9]` is a two digit number. + + ## Try: ```sh @@ -42,14 +44,16 @@ to visit the 64 squares without repeating them? If not, this program does it, just run it with an argument giving initial position. - ./toledo1 11 (start is A8) - ./toledo1 18 (start is H8) - ./toledo1 81 (start is A1) - ./toledo1 88 (start is H1) - ./toledo1 44 (start is D5) +```sh +./toledo1 11 # start is A8 +./toledo1 18 # start is H8 +./toledo1 81 # start is A1 +./toledo1 88 # start is H1 +./toledo1 44 # start is D5 +``` It will print move order. The algorithm is so simple that you can read -it on the source code, at the first glance it can appear checkered :-) +it in the source code, at the first glance it can appear checkered :-) but don't dismail, jar, jar. ## Copyright and CC BY-SA 4.0 License: diff --git a/2006/toledo2/.gitignore b/2006/toledo2/.gitignore index f993bed8b..07514efc8 100644 --- a/2006/toledo2/.gitignore +++ b/2006/toledo2/.gitignore @@ -1,2 +1,24 @@ +A +ADVENTUR/ +B +BASICS/ C +CPM64.COM +DBASEII/ +GAMES/ +KAYPROII.ZIP +KERMIT/ +MASTER/ +MFDISK/ +MODEM7/ +PRO8/ +SOURCE/ +THE-WORD/ +TINKER/ +WS33-1/ +WS33-2/ +WS33-KPR/ +WS33/ toledo2 +toledo2.alt +DDT.COM diff --git a/2006/toledo2/Makefile b/2006/toledo2/Makefile index 0e72fc14a..9a8b7c048 100644 --- a/2006/toledo2/Makefile +++ b/2006/toledo2/Makefile @@ -64,7 +64,7 @@ CDEFINE= # Include files that are needed to compile # -CINCLUDE= +CINCLUDE= -include unistd.h -include stdlib.h # Optimization # diff --git a/2006/toledo2/README.md b/2006/toledo2/README.md index f62252069..c25512b11 100644 --- a/2006/toledo2/README.md +++ b/2006/toledo2/README.md @@ -1,10 +1,9 @@ # Best of Show - Oscar Toledo - Av. Santa Cruz del Monte 9-304 - Ciudad Satelite. Edo. de Mexico - CP. 53110 - Mexico +Oscar Toledo G. +Familia Toledo +Mexico + ## To build: @@ -18,79 +17,127 @@ make ./toledo2 ``` +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed a segfault in +this program which was making it fail to work under macOS - it did not seem to +be a problem under linux, at least not fedora. The problem was wrong variable +types - implicit `int`s instead of `FILE *`s. It now works with both macOS and +linux. Thank you Cody! + +To end execution press `ctrl-z`. As mentioned in the author's remarks and in the +below section, it is supposed to crash on termination though Cody noted this +does not seem to happen in macOS. He asks ironically: 'if it's supposed to crash +and it does not crash is it actually a bug or is it a feature? :-)' + +### INABIAF - it's not a bug it's a feature! :-) + +By design this program is supposed to crash on termination. + +You must type in caps (except in strings) and this program is indeed +case-sensitive. + ## Try: ```sh -echo "Do or do not. There is no try." +./toledo2 + ``` +and then type in the following: + +``` +10 PRINT "HELLO WORLD!" +LIST +RUN +``` + +To end the program hit ctrl-z. + +### IABINAF - it's a bug it's not a feature! :-) + +Although the program does not crash when reading in `C.BIOS` it appears that the +CP/M emulator does not work as expected at least according to the author's +remarks. + +See also [bugs.md](/bugs.md) for more details. + ## Judges' remarks: -We're impressed! Last year, it was a 6502 emulator; this year, -it's 8080! It requires an input file ("C") to be present, but -it does not have to be one of C.BASIC or C.BIOS - you're welcome -to write a standalone 8080 program yourself! How about C.FORTH -or C.LISP? +We're impressed! Last year, it was a +[6502](https://en.wikipedia.org/wiki/MOS_Technology_6502) emulator; this year, +it's [8080](https://en.wikipedia.org/wiki/Intel_8080)! It requires an input file +(`C`) to be present, but it does not have to be one of `C.BASIC` or `C.BIOS` - +you're welcome to write a standalone 8080 program yourself! How about `C.FORTH` +or `C.LISP`? In addition to the functionality you could expect from a program of this size, it allows importing files from the host file system (one by one, so you'll have to be patient). Remember the good old days and play (or let your kids play) -Adventure (in the directory ADVENTUR within the KAYPROII.ZIP +[Adventure](https://rickadams.org/adventure/) (in the directory `ADVENTUR` +within the `KAYPROII.ZIP` file referred in the author's remarks); walking in a maze of twisty little passages all alike is easier than understanding the code! ## Author's remarks: -This program emulates a complete Intel(r) 8080 -processor, along with a teletype and a disk -controller, just like at the start of the personal -computers revolution (circa 1975). +This program emulates a complete [Intel(r) +8080](https://en.wikipedia.org/wiki/Intel_8080) processor, along with a teletype +and a disk controller, just like at the start of the personal computers +revolution (circa 1975). -It needs an initial memory image to do something -usable, so along it you will find two files -(C.BASIC and C.BIOS). Rename C.BASIC to C and run -the emulator, and et voila! you have the public -domain Palo Alto Tiny BASIC (by Li-Chen Wang), -published on the very first volume of Dr. Dobb's -Journal. +It needs an initial memory image to do something usable, so along with it you +will find two files ([C.BASIC](C.BASIC) and [C.BIOS](C.BIOS)). Rename +[C.BASIC](C.BASIC) to `C` (NOTE from the judges: running `make` will do this for +you), run the emulator, and et voila! you have the public domain Palo Alto [Tiny +BASIC](https://en.wikipedia.org/wiki/Tiny_BASIC) (by Li-Chen Wang), published in +the very first volume of [Dr. Dobb's +Journal](https://en.wikipedia.org/wiki/Dr._Dobb%27s_Journal). -Type using uppercase letters, here are three example -programs, press Enter after each line: +Type using uppercase letters. Here are three example programs. Press Enter after +each line: - 10 PRINT "Hello, world!" - LIST - RUN +```basic +10 PRINT "Hello, world!" +LIST +RUN - 10 FOR A=1 TO 10 10 INPUT A - 20 PRINT A 20 INPUT B - 30 NEXT A 30 PRINT A+B - LIST LIST - RUN RUN +10 FOR A=1 TO 10 +20 PRINT A +30 NEXT A +LIST +RUN -Press Ctrl+Z to quit, by the way, the segmentation fault is +10 INPUT A +20 INPUT B +30 PRINT A+B +LIST +RUN +``` + +Press Ctrl+Z to quit. By the way, the segmentation fault is normal at this point. -All good programmers started learning BASIC, now, what about a -CP/M emulator? +All good programmers started learning +[BASIC](https://en.wikipedia.org/wiki/BASIC), now, what about a +[CP/M](https://en.wikipedia.org/wiki/CP/M) emulator? Download the following file (not included because of possible copyright and blah, blah): > -Extract CPM64.COM from the SOURCE directory, and copy it to -files named A and B (these will be the disk drives). Now rename -the provided C.BIOS to C and run the emulator. +Extract `CPM64.COM` from the `SOURCE` directory, and copy it to +files named `A` and `B` (these will be the disk drives). Now rename +the provided [C.BIOS](C.BIOS) to `C` and run the emulator. -Now you have a running CP/M system!, with two files on A: drive, -HALT.COM to stop the emulator (so it closes drives) and IMPORT.COM -to introduce new files. +Now you have a running [CP/M](https://en.wikipedia.org/wiki/CP/M) system!, with +two files on A: drive, `HALT.COM` to stop the emulator (so it closes drives) and +`IMPORT.COM` to introduce new files. -To get a complete CP/M system, you will need the following files -from the KAYPROII.ZIP, SOURCE directory: +To get a complete [CP/M](https://en.wikipedia.org/wiki/CP/M) system, you will need the following files +from the `KAYPROII.ZIP` (in the `SOURCE` directory): ASM.COM DDT.COM DUMP.COM ED.COM LOAD.COM PIP.COM STAT.COM SUBMIT.COM XSUB.COM @@ -98,39 +145,44 @@ from the KAYPROII.ZIP, SOURCE directory: To import them, you must run the emulator with an argument, by example: - prog DDT.COM +```sh +./toledo2 DDT.COM +``` When the A> prompt appears, do: - IMPORT DDT.COM +``` +IMPORT DDT.COM +``` -When it ends, do HALT, so the file is saved, and you can start +When it ends, do `HALT`, so the file is saved, and you can start the same process with another file. At this time I have tested successfully the following software -from retroarchive.org: +from : -> -> -> +- +- +- -Some programs requiere installation to configure the terminal, +Some programs require installation to configure the terminal, locate ANSI or VT-100. ### What is an 8080? -It is simply the little brother of the Z80, it has no extended -registers (AF', BC', DE', HL', IX or IY), no relative jumps, -and every instruction beginning with CB, DD, ED or FD doesn't +It is simply the little brother of the +[Z80](https://en.wikipedia.org/wiki/Zilog_Z80); it has no extended +registers (`AF'`, `BC'`, `DE'`, `HL'`, `IX` or `IY`), no relative jumps, +and every instruction beginning with `CB`, `DD`, `ED` or `FD` doesn't exist. -The flags are only S (Sign, bit 7), Z (Zero, bit 6), P (Parity, -bit 2) and C (Carry, bit 0). +The flags are only `S` (Sign, bit 7), `Z` (Zero, bit 6), `P` (Parity, +bit 2) and `C` (Carry, bit 0). ### Porting it It is easy if your platform has getch/kbhit and -ANSI terminal +ANSI terminal: read --> Z=kbhit()?getch():0 write --> putchar(7[o]) @@ -141,34 +193,33 @@ Also add the following to trap Ctrl-C: #include signal(SIGINT, SIG_IGN); -On PC/DOS you need to add ANSI.SYS to CONFIG.SYS +NOTE from the judges: in Unix like systems `getch()` is part of curses but this +is not what is needed. -In *NIX the min 0 on stty is required, circa 2001 +On PC/DOS you need to add `ANSI.SYS` to `CONFIG.SYS`. + +In Unix the min 0 on `stty` is required but circa 2001 it was not required. -. -. -. ### How it works (SPOILER) -. -. -. - -The l array contains the 64K memory, it is initialized with a -boot image loaded from the 'C' file, the program counter is the -c pointer, and regitser are on o[]. The main loops reads every -op-code and separates it in one of three common forms, a lot -of trinary operators selects the instruction. +The `l` array contains the 64K memory; it is initialized with a +boot image loaded from the `C` file. The program counter is the +`c` pointer and registers are in `o[]`. The main loop reads every +opcode and separates them in one of three common forms. A lot +of ternary operators selects the instruction. +``` o[0] = B register o[1] = C register o[2] = D register o[3] = E register o[4] = H register o[5] = L register o[6] = Flags o[7] = A or accumulator +``` The following instructions do peripheral operation: +``` 76 Quits emulator DB 00 Reads key pressed status DB 01 Reads key @@ -176,33 +227,36 @@ The following instructions do peripheral operation: D3 xx Writes byte from acc. to console ED ED 02 Reads sector ED ED 03 Writes sector +``` Memory addresses: +``` FBFA = Low source/target direction FBFB - High source/target direction FBFC - Sector FBFD - Low cylinder FBFE - High cylinder FBFF - Drive. +``` The BIOS is tailor made for this emulator, and helps to simplify it. -Other notes: +### Other notes - The 8080 runs at your computer speed divided between a number that I have not calculated. - This obfuscated processor is created using - obfuscated code produced by an obfuscated mind, + obfuscated code produced by an obfuscated mind; no brains were harmed during its production, except those that tried to read the code. -- The original version of this code was eated +- The original version of this code was eaten by my C++ dog. -- I intended to make it simple to understand, +- I intended to make it simple to understand; it uses only four C keywords. - Also I discovered that braces are very useful for commenting. -- Why to bother with prototypes?, every good C +- Why bother with prototypes? Every good C programmer can develop its C programs using only one function. diff --git a/2006/toledo2/toledo2.c b/2006/toledo2/toledo2.c index f65cbf3bf..c441c13c5 100644 --- a/2006/toledo2/toledo2.c +++ b/2006/toledo2/toledo2.c @@ -1,4 +1,6 @@ #include + #include + #include #define n(o,p,e)=y=(z=a(e)%16 p x%16 p o,a(e)p x p o),h( #define s 6[o] #define p z=l[d(9)]|l[d(9)+1]<<8,1<(9[o]+=2)||++8[o] @@ -17,7 +19,7 @@ unsigned char o[10],l[78114],*c=l,*k=l #define d(e)o[e]+256*o[e-1] #define h(l)s=l>>8&1|128&y|!(y&255)*64|16&z|2,y^=y>>4,y^=y<<2,y^=~y>>1,s|=y&4 -+64506; e,V,v,u,x,y,z,Z; main(r,U)char**U;{ ++64506; FILE *u, *v, *e, *V; int x,y,z,Z; main(r,U)char**U;{ { { { } } } { { { } } } { { { } } } { { { } } } { { { } } } { { { } } } { { { } } } { { { } } } diff --git a/2006/toledo3/README.md b/2006/toledo3/README.md index fd6d75af7..3a4b132e4 100644 --- a/2006/toledo3/README.md +++ b/2006/toledo3/README.md @@ -1,10 +1,9 @@ # Most Portable Chess Set - Oscar Toledo - Av. Santa Cruz del Monte 9-304 - Ciudad Satelite. Edo. de Mexico - CP. 53110 - Mexico +Oscar Toledo G. +Familia Toledo +Mexico + ## To build: @@ -18,12 +17,28 @@ make ./toledo3 [1 | 2 | 3 [b]] ``` +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed a crash and a +display problem in this entry so that it would work in modern (64-bit) systems. +The problem was that it relied on 32-bits so some `int`s were changed to +`long`s. At this time we don't have an easy way to test this theory but it might +be that using `-m32` would let this work in 32-bit systems. Thank you Cody for +your assistance! + ## Try: ```sh ./toledo3 1 ``` +### Alternate versions: + +The author provided two additional versions, [toledo3-sbar.c](toledo3-sbar.c) +and [toledo3-txt.c](toledo3-txt.c). Respectively these create a status bar and +make the game text only. These are built by default. + +Use `toledo3-sbar` and `toledo3-txt` as you would `toledo3` above. + + ## Judges' remarks: It's pretty obvious from looking at it what this program does, @@ -34,12 +49,11 @@ the code for Deep Blue. ## Author's remarks: There are so many text-based chess programs, what is that of -A1, H5, C4, D5? The queen is really pointing to the king? +`A1`, `H5`, `C4`, `D5`? The queen is really pointing to the king? -So I managed to do a graphical X11 chess program (WYSIAIE, or -What You See Is An IOCCC Entry), point'n'click to move pieces -is the only required action, and of course the command-line -options: +So I managed to do a graphical X11 chess program ('`WYSIAIE`', or 'What You See +Is An IOCCC Entry'). Pointing and clicking to move pieces is the only required +action, and of course the command-line options: ```sh ./toledo3 # Two-players mode (useful if you don't have a board at hand) @@ -51,7 +65,7 @@ options: ./toledo3 3 b # Human black - Computer white, level 3 (slow) ``` -The computer will check that your moves are legal, full legal +The computer will check that your moves are legal. Full legal chess moves are allowed, except minor promotions on human side. The game will continue up to its logical conclusion, you make @@ -59,37 +73,38 @@ a mistake and the computer surpasses you. ;) ### WHAT ABOUT THE ENGINE -Uses an alpha-beta search up to a depth of 3+level ply, extended -with quiescence search, that helps playing strength, something -around 1500 ELO (level 1) to 1700 ELO (level 3) +Uses an [alpha-beta](https://en.wikipedia.org/wiki/Alpha_Beta) search up to a +depth of 3+level [ply](https://en.wikipedia.org/wiki/Ply_(game_theory)), +extended with quiescence search, that helps playing strength, something around +1500 ELO (level 1) to 1700 ELO (level 3). -It searches the board and generates moves for each piece located, -a lot of comparisons are used for empassant, castling and -promotion. Would be faster with optimizations, but that +It searches the board and generates moves for each piece located. A lot of +comparisons are used for [en passant](https://en.wikipedia.org/wiki/En_passant), +castling and promotion. Would be faster with optimizations, but that optimizations use valuable IOCCC characters. It plays a different game every time, using the C library random number generator. Because it is resource-hungry, I strongly recommend to compile it -using maximum optimization, on GCC you can use: +using maximum optimization. With GCC you can use: -``` +```sh gcc -O3 -fexpensive-optimizations prog.c -o prog -lX11 ``` ### KNOWN "FEATURES" 1. Because this is my second X11 program (the first was - point'n'click happy face), I added sentences everywhere + point n click happy face), I added sentences everywhere until it worked. :) -2. It is portable to Wind*ws (using the supplied layer.c file) - Change #include to #include "layer.c" and - use a Wind*ws compiler (only tested with Dev C/C++ 4.9.9.2) +2. It is portable to Windows (using the supplied layer.c file) + Change `#include to #include "layer.c"` and + use a Windows compiler (only tested with Dev C/C++ 4.9.9.2) The play level is fixed, though you can change it easily. - Of course, this is an example of an obfuscated Wind*ws - program (there exists another way of write them?) + Of course, this is an example of an obfuscated Windows + program (there exists another way of write them?). 3. It will give warnings on compilation, so you can be sure that your compiler works. @@ -97,13 +112,13 @@ gcc -O3 -fexpensive-optimizations prog.c -o prog -lX11 4. It will not update the window while it is "thinking" 5. The space character has many useful applications, specially - when it comes about the character limit. 8) + when it comes to the character limit (8). 6. I still don't understand what to do after semicolons. :P ### CHALLENGES -It is possible to convert this code into Javascript with a +It is possible to convert this code into JavaScript with a graphical interface. Can you do it? Can the evaluation function be enhanced to make the program @@ -111,10 +126,10 @@ play stronger? ### UPGRADES -Using toledo3-sbar.c (which is too large for this IOCCC size -rules) creates a status display about gameplay on the window title bar, +Using [toledo3-sbar.c](toledo3-sbar.c) (which is too large for this IOCCC size +rules) creates a status display about gameplay on the window title bar. -Using toledo3-txt.c turns this into being purely text based. +Using [toledo3-txt.c](toledo3-txt.c) turns this into being purely text based. ## Copyright and CC BY-SA 4.0 License: diff --git a/2006/toledo3/toledo3-sbar.c b/2006/toledo3/toledo3-sbar.c index d2e0f18d9..ba055fe55 100644 --- a/2006/toledo3/toledo3-sbar.c +++ b/2006/toledo3/toledo3-sbar.c @@ -10,11 +10,11 @@ Plane(d, r[I[A]+7+14*(i+b>>6&1)+28*(A==z)],w,C,0,0,64,64,b,i,1); XFlush(d); #define a X(0,0,0, #define H while( #define D ;if( - +long I[304],b,i,z;main(x,W) char**W; { Display *d = XOpenDisplay(""); Window w = XCreateSimpleWindow (d, DefaultRootWindow(d), 64,64,512,512,2,G(Black) - ,G(Black)); XGCValues g; XButtonEvent e; int A,r + ,G(Black)); XGCValues g; XButtonEvent e; long A,r [56],Z,* m = I , C ,Y; XSelectInput(d,w,32772); XMapWindow( d, w); g. foreground = G(White); C=XCreateGC(d,w,4,&g); F+=48; H f=I,i=0,z<56){ diff --git a/2006/toledo3/toledo3.c b/2006/toledo3/toledo3.c index 53290a631..8d5dd8e62 100644 --- a/2006/toledo3/toledo3.c +++ b/2006/toledo3/toledo3.c @@ -11,10 +11,11 @@ Plane(d, r[I[A]+7+14*(i+b>>6&1)+28*(A==z)],w,C,0,0,64,64,b,i,1); XFlush(d); #define H while( #define D ;if( +long I[304],b,i,z;main(x,W) char**W; { Display *d = XOpenDisplay(""); Window w = XCreateSimpleWindow (d, DefaultRootWindow(d), 64,64,512,512,2,G(Black) - ,G(Black)); XGCValues g; XButtonEvent e; int A,r + ,G(Black)); XGCValues g; XButtonEvent e; long A,r [56],Z,* m = I , C ,Y; XSelectInput(d,w,32772); XMapWindow( d, w); g. foreground = G(White); C=XCreateGC(d,w,4,&g); F+=48; H f=I,i=0,z<56){ diff --git a/2011/akari/README.md b/2011/akari/README.md index 1eff3022a..ee75a8b74 100644 --- a/2011/akari/README.md +++ b/2011/akari/README.md @@ -1,8 +1,8 @@ # Best of Show - Most Shrinkable - Don Yang - - +Don Yang + + ## To build: @@ -13,7 +13,7 @@ make ## To run: ```sh -./akari [input_file_or_- [output_file_or_- [even]]] +./akari [ input_file | - ] [ output_file | - ] [even] ``` ## Try: @@ -26,16 +26,12 @@ make make akari2 cat akari2.c -make akari2 - ./akari2 < akari2.c ./akari2 rot13 < akari2.c make akari3 cat akari3.c -make akari3 - ./akari3 make akari4 @@ -44,89 +40,109 @@ cat akari4.c ./akari4 ``` +You can automate the above by running: + +```sh +./try.me.sh +``` + ## Judges' remarks: -Akari is an image downsampling utility that accepts 3 inout formats: +`Akari` is an image downsampling utility that accepts 3 input formats: - * PGM (netpbm grayscale image). Akari only accept PGM files with this - header: P5 255. Images with extra comments such as - the ones produced by GIMP will not be parsed properly. +* `PGM` (`netpbm` greyscale image). `Akari` only accepts `PGM` files with this +header: `P5 255`. Images with extra comments _such as the ones +produced by GIMP will **not be parsed properly**_. - * PPM (netpbm RGB image). Only PPM files with this header are - accepted: P6 255. +* PPM (netpbm RGB image). Only PPM files with this header are + accepted: `P6 255`. - * ASCII art (with end of lines in LF bytes only, not CR-LF) +* ASCII art (with end of lines in LF bytes only, _**not** CRLF_!) -Anything that is not parseable as PGM or PPM will be downsampled as ASCII art. +Anything that is not parsable as `PGM` or `PPM` will be downsampled as ASCII art. ## Author's remarks: -Akari is an image downsampling utility. She accepts up to 3 arguments: +`Akari` is an image downsampling utility. She accepts up to 3 arguments: -First argument is the input image. If it's "-" or unspecified, Akari +First argument is the input image. If it's `-` or unspecified, `Akari` will read from stdin. -Second argument is the output image. If it's "-" or unspecified, -Akari will write to stdout. +Second argument is the output image. If it's `-` or unspecified, +`Akari` will write to stdout. -Third argument, if specified, causes Akari to keep even pixels on even -scanlines. By default Akari will keep odd pixels on odd scanlines. +Third argument, if specified, causes `Akari` to keep even pixels on even +[scanlines](https://en.wikipedia.org/wiki/Scan_line). By default `Akari` will +keep odd pixels on odd [scanlines](https://en.wikipedia.org/wiki/Scan_line). -Examples: +### Examples: - gcc akari.c -o akari - ./akari < example.ppm > odd_output.ppm - ./akari - - even < example.ppm > even_output.ppm - ./akari example.ppm odd_output.ppm +```sh +gcc akari.c -o akari +./akari < example.ppm > odd_output.ppm +./akari - - even < example.ppm > even_output.ppm +./akari example.ppm odd_output.ppm +``` -Akari accepts 3 input formats: -* PGM (netpbm grayscale image). Akari only accept PGM files with this - header: P5 255. Images with extra comments such as +`Akari` accepts 3 input formats: + +* `PGM` (`netpbm greyscale image`). `Akari` only accepts `PGM` files with this + header: `P5 255`. Images with extra comments such as the ones produced by GIMP will not be parsed properly. -* PPM (netpbm RGB image). Only PPM files with this header are - accepted: P6 255. +* `PPM` (`netpbm RGB image`). Only `PPM` files with this header are + accepted: `P6 255`. * ASCII art (with end of lines in LF bytes only, not CR-LF) This is useful for decoding some curiously interlaced images, such as the included example.ppm -Anything that is not parseable as PGM or PPM will be downsampled as +Anything that is not parsable as `PGM` or `PPM` will be downsampled as ASCII art. Since the source code is formatted as ASCII art, it's only natural to try: - ./akari akari.c akari2.c +```sh +./akari akari.c akari2.c +``` -akari2.c is also a valid C program, and accepts up to 1 argument. +`akari2.c` is also a valid C program, and accepts up to 1 argument. By default, this second program reads text from stdin and writes expanded output to stdout. If the extra argument is specified, the output text will also pass through a rot13 filter. - gcc akari2.c -o akari2 - ./akari2 < input.txt > expanded_output.txt - ./akari2 rot13 < input.txt > expanded_and_rot13_output.txt +```sh +gcc akari2.c -o akari2 +./akari2 < input.txt > expanded_output.txt +./akari2 rot13 < input.txt > expanded_and_rot13_output.txt +``` You can combine the two programs together to have just a regular rot13 filter: - ./akari2 rot13 < input.txt | ./akari > rot13.txt +```sh +./akari2 rot13 < input.txt | ./akari > rot13.txt +``` Of course, we wouldn't stop with just 2 programs, you can downsample the source *again* and get yet another C program: - ./akari < akari.c | ./akari > akari3.c +```sh +./akari < akari.c | ./akari > akari3.c +``` We must go deeper: - ./akari < akari.c | ./akari | ./akari > akari4.c +```sh +./akari < akari.c | ./akari | ./akari > akari4.c +``` -akari3.c and akari4.c are still (mostly valid) C programs. -"gcc -Wall" will output a few warnings, but still produce output +`akari3.c` and `akari4.c` are still (mostly valid) C programs. +`gcc -Wall` will output a few warnings, but still produce output executables. The output executables each print a message to stdout. It takes quite a bit of skill and obfuscation to interleave a C program 4 levels deep, it's much easier to interleave something like -a brainf#$% program in a C program, for example. For comparison, a -brainf#$% program is embedded inside akari.c +a `brainf#$%` program in a C program, for example. For comparison, a +`brainf#$%` program is embedded inside [akari.c](akari.c). ## Copyright and CC BY-SA 4.0 License: diff --git a/2011/akari/try.me.sh b/2011/akari/try.me.sh new file mode 100755 index 000000000..08cc310ef --- /dev/null +++ b/2011/akari/try.me.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +make clobber akari || exit 1 + +./akari < example.ppm > odd_output.ppm +./akari - - even < example.ppm > even_output.ppm +./akari example.ppm odd_output.ppm + +make akari2 || exit 1 +cat akari2.c + +./akari2 < akari2.c +./akari2 rot13 < akari2.c + +make akari3 || exit 1 +cat akari3.c + +./akari3 + +make akari4 || exit 1 +cat akari4.c + +./akari4 diff --git a/2011/blakely/.gitignore b/2011/blakely/.gitignore index 5c36c9097..92abbda70 100644 --- a/2011/blakely/.gitignore +++ b/2011/blakely/.gitignore @@ -1 +1,2 @@ blakely +garden.txt diff --git a/2011/blakely/README.md b/2011/blakely/README.md index c02bea6a6..d15bdae8c 100644 --- a/2011/blakely/README.md +++ b/2011/blakely/README.md @@ -1,8 +1,8 @@ # Most devolving - Philip Blakely - Cambridge, UK - +Philip Blakely +Cambridge, UK + ## To build: @@ -29,7 +29,8 @@ Zoom out and make your terminal window 53 or more lines deep. ## Judges' remarks: -This program plays Life, computes Pi to 16 digits +This program plays [Life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life) +(see also [here](https://conwaylife.com)), computes Pi to 16 digits if given its own source as input, and allows to check if your garden is a [Garden of Eden](http://en.wikipedia.org/wiki/Garden_of_Eden_%28cellular_automaton%29), all in one source. @@ -42,8 +43,6 @@ and run: ## Author's remarks: -### Remarks - This program uses a well-known algorithm in order to display pi to fifteen decimal places. The source-layout itself demonstrates the importance of using the correct amount of whitespace in code and the clear superiority of spaces over tabs. @@ -61,20 +60,20 @@ high and wide. Alternatively, redirect the output to a separate file ### Overview -The program emulates John Conway's ceullular automaton known as "The -Game of Life", using standard input as a starting grid. The layout of -the source-code is such that it evolves to a digital representation of -the first 15 decimal places of pi after 4 time steps. This was setup -using the other feature of the program which can be demonstrated as follows: +The program emulates John Conway's cellular automaton known as "[The Game of +Life](https://conwaylife.com)", using standard input as a starting grid. The +layout of the source-code is such that it evolves to a digital representation of +the first 15 decimal places of pi after 4 time steps. This was setup using the +other feature of the program which can be demonstrated as follows: ```sh ./blakely - < 3.dat ``` -The program will first display the grid given in 3.dat, and then three +The program will first display the grid given in [3.dat](3.dat), and then three more grids (taking a few minutes to display the last). Waiting for any more grids will take a substantial amount of time. The final grid has been put into -evolve\_to\_3.dat, and if you type +[evolve_to_3.dat](evolve_to_3.dat), and if you type ```sh ./blakely < evolve_to_3.dat @@ -82,25 +81,25 @@ evolve\_to\_3.dat, and if you type then the 3 will reappear after three time steps. -As should now be clear, this use of program will attempt to evolve a given setup backwards in -time according to the Life rules. The resulting grid is clearly not -necessarily unique. The program will evolve backwards given *any* single -command line option. +As should now be clear, this use of program will attempt to evolve a given setup +backwards in time according to the Life rules. The resulting grid is clearly not +necessarily unique. The program will evolve backwards given *any* single command +line option. When evolving forwards, the code can only be stopped by killing the program. In the reverse direction, the code can either be killed, or will stop if it is unable to find a grid that will evolve to the current layout correctly. This can be seen with the sample grid -t0_3.dat, which evolves backwards by only two time-steps. +[t0_3.dat](t0_3.dat), which evolves backwards by only two time-steps. ### Input file format -The input files must encode a square grid, where a space is a dead -cell, and any other character (except a newline) is a living cell. Each line must be the same -length, and end with a single newline character \n (ASCII 10), including the last line. When -designing grids, it may help to type full-stops in place of spaces, -and do a global replace afterwards. Any deviation from this format will -cause errors in the output. +The input files must encode a square grid, where a space is a dead cell, and any +other character (except a newline) is a living cell. Each line must be the same +length, and end with a single newline character `\n` (ASCII 10), including the +last line. When designing grids, it may help to type full-stops (dots) in place +of spaces, and do a global replace afterwards. Any deviation from this format +will cause errors in the output. ### Limitations @@ -114,48 +113,47 @@ such for the following time-step, although any living cells on the right border will never be displayed. The maximum grid size is currently 99 by 99 (exceeding this will cause a -seg-fault), but changing the two 9802s to MAX\_SIZE*MAX\_SIZE+1 will -solve this, although some reformatting of the -code may have to be done to allow larger numbers. +segfault), but changing the two `9802`s to `MAX_SIZE*MAX_SIZE+1` will +solve this, although some reformatting of the code might have to be done to allow +larger numbers. ### Compiler warnings/assumptions -When compiled with the -Wall -pedantic -ansi options of gcc, some -warnings suggesting extra parentheses occur (not necessary for anyone -fully conversant with operator precedence). There is one unused -variable, v, but unnamed function parameters are not permitted in ANSI -C, so naming it is necessary, and gcc no longer warns about its -existence, although earlier versions did. +When compiled with the `-Wall -pedantic -ansi` options of gcc, some warnings +suggesting extra parentheses occur (not necessary for anyone fully conversant +with operator precedence). There is one unused variable, `v`, but unnamed +function parameters are not permitted in ANSI C, so naming it is necessary, and +gcc no longer warns about its existence, although earlier versions do. -Since the program calculates ASCII character values for display, an -ASCII based system is required to run it. Also, as mentioned above, -any system that uses anything other than a plain '\n' to end a line will cause -problems when reading in files. +Since the program calculates ASCII character values for display, an ASCII based +system is required to run it. Also, as mentioned above, any system that uses +anything other than a plain `\n` to end a line will cause problems when reading +in files. -### Obfuscations +### Obfuscation Given the finely-tuned layout required to evolve into pi, this is one of the main obfuscations used in the code. However, running the code through the -preprocessor, expanding the defines, and applying GNU's indent, although +preprocessor, expanding the `#define`s, and applying GNU's indent, although making the location of functions and statements clear, by no means makes the -code entirely clear. Note that expanding out the #defines does not take the +code entirely clear. Note that expanding out the `#define`s does not take the program over the character limit. The main reason for these is to do with the layout, since there are few places that keywords or tokens of over 2 -characters can be fitted, and requiring the first few lines to be #includes +characters can be fitted, and requiring the first few lines to be `#include`s would cause similar problems. Other obfuscations used are: -- Use of the classic 2[a] syntax to access the third element of the - array a +- Use of the classic `2[a]` syntax to access the third element of the + array `a`. - Nested ternary operators, combined with shortcut evaluation being - required for correct operation -- Use of the comma operator to embed operations inside one another -- Calculation of ASCII codes -- Needlessly recursive functions + required for correct operation. +- Use of the comma operator to embed operations inside one another. +- Calculation of ASCII codes. +- Needlessly recursive functions. - Use of bitwise-operations. -- Storing a variable whose value could easily be found from another -- Use of gotos to emulate a for loop +- Storing a variable whose value could easily be found from another. +- Use of `goto`s to emulate a for loop. ### Algorithm @@ -184,7 +182,8 @@ caused a substantial slowdown.) ### Program layout The "calculation" of pi was chosen purely because algorithms to find -pi are numerous, but the Game of Life is rarely (if ever?) used for +pi are numerous, but the [Game of +Life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life) is rarely (if ever?) used for this purpose. Also, separate digits made determining the layout somewhat easier. Deriving the layout was the most complicated part of the program. As is clear from @@ -200,28 +199,30 @@ into. Therefore it was necessary to add some regions that would quickly die off without expanding to collide with the digits' evolution. Groups of cells such as singletons, pairs, and larger groups like +``` * * * * * * * * * * ***************** * * * * * * * * * * +``` were useful in this regard. Other problems were given by keywords which need to be all in one string, keywords requiring space after them, and multi-character tokens. Some of these problems were dealt with by -using the #defines and #includes given in the build-script, as there +using the `#define`s and `#include`s given in the build-script, as there was no way to have sufficient separate lines in the code to do this without causing many difficulties. Some rejigging of the grid's layout as the code was fitted into its format was also done, resorting to trial-and-improvement in some cases. Occasional use of constructs such -as f -= -3 was made as f += 3 could not be fitted into the required format. +as `f -= -3` was made as `f += 3` could not be fitted into the required format. The fact that the borders would be killed off immediately was also helpful. It should be noted that evolving a full 60-by-60 grid backwards using this code would probably take us at least up to the heat-death of the universe. -The command ./blakely - < blakely.c is therefore *not* recommended. +The command `./blakely - < blakely.c` is therefore *not* recommended. ## Copyright and CC BY-SA 4.0 License: diff --git a/2011/borsanyi/README.md b/2011/borsanyi/README.md index 5d83e1b17..dcb832535 100644 --- a/2011/borsanyi/README.md +++ b/2011/borsanyi/README.md @@ -1,11 +1,8 @@ # Best data utility - Szabolcs Borsanyi - Theoretische Physik - Gaussstraße 20 - 42097 Wuppertal - Germany - +Szabolcs Borsanyi +Germany + ## To build: @@ -29,20 +26,22 @@ make ## Judges' remarks: -This is a nice quick histogram plotter. A useful utility when you need to -look at the distribution of some data. +This is a nice quick [histogram](https://en.wikipedia.org/wiki/Histogram) +plotter. A useful utility when you need to look at the distribution of some +data. Here are some challenges: -You can modify the number of histogram bins and the scaling of the histogram -by editing the source. Try to find them! +You can modify the number of histogram +[bins](https://en.wikipedia.org/wiki/Data_binning) and the scaling of the +histogram by editing the source. Try to find them! If you look at the source you will notice that the usual array of histogram bins is missing. The source contains no arrays and it does not -use malloc or alloca. How does it build the histogram? +use `malloc(3)` or `alloca(3)`. How does it build the histogram? While the input does not need to be sorted, the histogram output is sorted. -How does it put the data into buckets? Why does it fork 22 times? +How does it put the data into buckets? Why does it `fork()` 22 times? ## Author's remarks: @@ -52,20 +51,20 @@ histogram. I am all too often logged in to a remote machine with slow X connection, and a terminal-based program would be of great help. -### Limitations: +### Limitations * I optimized the output for the data I had around, you might want to adjust for your needs. For a great excess of data points the program will crash (depending on the available stack). * Giving too few (distinct) points can also cause crash (or division by zero). * The program expects plain numbers separated by white spaces. -* ASCII is assumed. -* Some POSIX-like system is assumed (fork and wait(NULL) are used) +* ASCII is assumed. +* Some POSIX-like system is assumed (`fork()` and `wait(NULL)` are used). * Do not give any arguments to the program. * Could rounding errors cause the omission of the highest bin? There might be empty bins at the edges. -### Obfuscation: +### Obfuscation * The program follows a rather unconventional approach to the task of histogram building. The usual array of integers (for the histogram diff --git a/2011/dlowe/README.md b/2011/dlowe/README.md index 287922c9f..3b9b8146c 100644 --- a/2011/dlowe/README.md +++ b/2011/dlowe/README.md @@ -1,11 +1,7 @@ # Most self deprecating - David Lowe - 434 Tenney Drive - Rogue River, OR - 97537 - - +David Lowe + ## To build: @@ -19,9 +15,9 @@ make ./dlowe - corpus1/ [...] corpus0/ < start.net > trained.net ``` -NOTE: In the above command, the directory args MUST end in a "/". +NOTE: In the above command, the directory args MUST end in a `/`. -Then to use the `trained.net`: +Then to use `trained.net`: ```sh ./dlowe file [file ...] < trained.net @@ -40,12 +36,15 @@ Try these pre-trained networks: ./dlowe xor-1/01 < dlowe-aux-data/xor-trained.net ./dlowe xor-1/10 < dlowe-aux-data/xor-trained.net -./dlowe hint.html < dlowe-aux-data/english-trained.net +./dlowe README.md < dlowe-aux-data/english-trained.net ./dlowe dlowe-aux-data.tar.bz2 < dlowe-aux-data/png-trained.net ``` -NOTE: The `dlowe-aux-data.tar.bz2/` directory was created by: +You can run `./try.me.sh` to do the same thing. + +NOTE: The `dlowe-aux-data/` directory was created by: + ```sh tar -jxf dlowe-aux-data.tar.bz2 @@ -56,12 +55,18 @@ tar -jxf dlowe-aux-data.tar.bz2 This entry is a ghoulish example of a brain (dead?) neural network classifier. It comes with a set of corpora for you to try. -### ioccc-winlose-trained.net +NOTE: the author's website, http://www.pootpoot.net, no longer exists (as the +same) and the Internet Wayback Machine did not load scripts. Do you know if the +domain changed? Please provide us with the proper URL or if you know if it was +shut down for ever, please let us know that. Thank you! + +### `ioccc-winlose-trained.net` You can create your own trained networks. For example, we trained a network on the C code of entries that were supplied to the 20Th IOCCC. -The ioccc-winlose-trained.net was trained using the earlystop.pl tool: +The `ioccc-winlose-trained.net` was trained using the +[earlystop.pl](earlystop.pl) tool: ```sh rm -f ioccc-winlose-trained.net @@ -70,101 +75,113 @@ rm -f ioccc-winlose-trained.net where: - ioccc_won_training/ - 1/2 of C code of the 20th IOCCC winners (except for dlowe.c from 2011) - plus 1/2 of the C code winners from prior IOCCC contests +- `ioccc_won_training/` + 1/2 of C code of the 20th IOCCC winners (except for [dlowe.c](dlowe.c) from 2011) + plus 1/2 of the C code winners from prior IOCCC contests - ioccc_won_test/ - 1/2 of C code of the 20th IOCCC winners (except for dlowe.c from 2011) - plus 1/2 of the C code winners from prior IOCCC contests +- `ioccc_won_test/` + 1/2 of C code of the 20th IOCCC winners (except for [dlowe.c](dlowe.c) from 2011) + plus 1/2 of the C code winners from prior IOCCC contests - ioccc_lost_training/ - 1/2 of C code from entries that that did not win +- `ioccc_lost_training/` + 1/2 of C code from entries that that did not win - ioccc_lost_test/ - 1/2 of C code from entries that that did not win +- `ioccc_lost_test/` + 1/2 of C code from entries that that did not win - NOTE: The above directies were not shipped and the C code from - entries that that did not win was flushed to /dev/null. +NOTE: The above directories were not shipped and everything from the entries +that did not win were flushed to `/dev/null`. -The earlystop.pl tool wrote: +The [earlystop.pl](earlystop.pl) tool wrote: training 1 to 1001... training 1001 to 2001... prior error = 56.746974766043; current error = 58.095691135305 -The resulting ioccc-winlose-trained.net file was included in the -dlowe-aux-data.tar.bz2 file in the above mentioned URL. +The resulting `ioccc-winlose-trained.net` file was included in the +[dlowe-aux-data.tar.bz2](dlowe-aux-data.tar.bz2) tarball. -The dlowe.c was explicitly excluded from this trailing set. So this test is interesting: +The [dlowe.c](dlowe.c) was explicitly excluded from this trailing set, so this +test is interesting: ```sh -./dlowe dlowe.c < ioccc-winlose-trained.net +./dlowe dlowe.c < dlowe-aux-data/ioccc-winlose-trained.net ``` -The match of dlowe.c to the lose/win trailed network was: +The match of [dlowe.c](dlowe.c) to the lose/win trailed network was: - dlowe.c 0.125108 +``` +dlowe.c 0.125108 +``` NOTE: The non-artificially intelligent decisions of the IOCCC judges include random - quirks and their non-linear judgment calls not found in the ioccc trained network. - Just because C code is or isn't scored highly by this network does not - mean it will win or lose a future IOCCC. On the other hand ... it just might! +quirks and their non-linear judgment calls not found in the ioccc trained network. +Just because C code is or isn't scored highly by this network does not +mean it will win or lose a future IOCCC. On the other hand ... it just might! #### other data sets to try While we cannot supply you with the losing IOCCC source code, the author did supply a number data sets on which to test: -We created the english-trained.net as follows: +We created the [english-trained.net](dlowe-aux-data/english-trained.net) as follows: ```sh -./dlowe -8000 english-1/ english-0/ < /dev/null > english-trained.net +./dlowe -8000 dlowe-aux-data/english-1/ dlowe-aux-data/english-0/ < /dev/null > dlowe-aux-data/english-trained.net ``` - english-0/ - Non-English (French) text - english-1/ - English (non-French) text +- [dlowe-aux-data/english-0/](dlowe-aux-data/english-0/) + Non-English (French) text -We created the png-trained.net as follows: +- [dlowe-aux-data/english-1/](dlowe-aux-data/english-1) + English (non-French) text + +We created the [png-trained.net](dlowe-aux-data/png-trained.net) as follows: ```sh -./dlowe -8000 png-1/ png-0/ < /dev/null > png-trained.net +./dlowe -8000 png-1/ png-0/ < /dev/null > dlowe-aux-data/png-trained.net ``` - png-0/ +- [dlowe-aux-data/png-0/](dlowe-aux-data/png-0/) Non-png (gif) images - png-1/ + +- [dlowe-aux-data/png-1/](dlowe-aux-data/png-1/) png (non-gif) images -We created the xor-trained.net as follows: +We created the [xor-trained.net](dlowe-aux-data/xor-trained.net) as follows: ```sh -./dlowe -8000 xor-1/ xor-0/ < /dev/null > xor-trained.net +./dlowe -8000 dlowe-aux-data/xor-1/ dlowe-aux-data/xor-0/ < /dev/null > dlowe-aux-data/xor-trained.net ``` - xor-0/ +- [dlowe-aux-data/xor-0](dlowe-aux-data/xor-0/) Data that XORs to 0 - xor-1/ + +- [dlowe-aux-data/xor-1/](dlowe-aux-data/xor-1/) Data that XORs to 1 +**NOTE**: The directory args **must end in a** `/` for them to work. + ## Author's remarks: -### Synopsis: +### Synopsis -This is an artificially intelligent judging tool to help the IOCCC judges. -Here's to shorter, more frequent contests! +This is an [artificially +intelligent](https://en.wikipedia.org/wiki/Artificial_intelligence) judging tool +to help the IOCCC judges. Here's to shorter, more frequent contests! -### Description: +### Description -This is a multilayer perceptron (a feedforward artificial neural network) -which can be trained, using on-line backpropagation, to classify input files. +This is a multilayer [perceptron](https://en.wikipedia.org/wiki/Perceptron) (a +[feedforward artificial neural +network](https://en.wikipedia.org/wiki/Feedforward_neural_network)) +which can be trained, using on-line +[backpropagation](https://en.wikipedia.org/wiki/Backpropagation), to classify input files. -It has a fixed topology of 2^16 input neurons, 6 hidden neurons and 1 output +It has a fixed topology of `2^16` input neurons, 6 hidden neurons and 1 output neuron. -The neurons' activation function is the logistic function 1 / (1 + e ^ -x). +The neurons' activation function is the logistic function `1 / (1 + e ^ -x)`. ### Classifying @@ -188,7 +205,7 @@ trained, but it's geared toward interpretation as a *probability* or a ./dlowe - corpus1/ [...] corpus0/ < start.net > end.net ``` - NOTE: The directory args must end in a / for them to work. +**NOTE**: The directory args **must end in a** `/` for them to work. To train a network, one specifies a starting network (on stdin), two or more corpora (directories containing training data), and the number of training @@ -202,70 +219,80 @@ The first corpus will be assigned a target value of 1. The last will be assigned a target value of 0. Intervening directories (if any) will be assigned intermediate target values. -The learning rate is hard-coded as 0.3. No momentum factor is used. +The learning rate is hard-coded as `0.3`. No momentum factor is used. #### png corpora -The png-1 corpus was obtained by manually scraping the first results from an -https://images.google.com search for "obfuscate filetype:png". +The [png-1](dlowe-aux-data/png-1) corpus was obtained by manually scraping the first results from an + search for "[obfuscate +filetype:png](https://www.google.com/search?tbm=isch&sxsrf=APwXEddqIU34dxhpFdjEa8emNJKHOkYXIw:1683049158657&source=hp&biw=1727&bih=952&ei=xkpRZLapJtLKkPIP8bGKkAk&iflsig=AOEireoAAAAAZFFY1nbmEUHC74Cmg3Y5rEY1fV7ocASZ&ved=0ahUKEwi2pPXZltf-AhVSJUQIHfGYApIQ4dUDCAY&uact=5&oq=obfuscate+filetype:png&gs_lcp=CgNpbWcQA1AAWABg9QNoAHAAeACAATuIATuSAQExmAEAoAECoAEBqgELZ3dzLXdpei1pbWc&sclient=img&q=obfuscate&tbs=ift:png)". -The png-0 corpus was obtained by manually scraping the first results from an -https://images.google.com search for "obfuscate filetype:gif". +The [png-0](dlowe-aux-data/png-0) corpus was obtained by manually scraping the first results from an + search for "[obfuscate +filetype:gif](https://www.google.com/search?tbm=isch&ved=2ahUKEwiowo7fltf-AhXSOUQIHbJBDp8Q2-cCegQIABAA&oq=obfuscate+filetype:gif&gs_lcp=CgNpbWcQAzoECCMQJzoHCAAQigUQQzoFCAAQgARQ6AxY6AxgpBJoAHAAeACAAUeIAcsBkgEBM5gBAKABAaoBC2d3cy13aXotaW1nwAEB&sclient=img&ei=0UpRZOiVINLzkPIPsoO5-Ak&bih=952&biw=1727&q=obfuscate&tbs=ift:gif)". -Results: +##### Results: - * using these corpora as a training set - * using several hundred random *.gif and *.png files from my home computer as - a test set - * using the included "earlystop.pl" script, which stopped after 67000 iterations. - * interpreting output of "> 0.5" as "probably a .png" and "< 0.5" as "probably - a .gif" - * produced a network with about 87% accuracy +* Using these corpora as a training set; +* Using several hundred random `*.gif` and `*.png` files from my home computer as + a test set; +* Using the included [earlystop.pl](earlystop.pl) script, which stopped after 67000 iterations. +* Interpreting output of `> 0.5` as "probably a `.png`" and `< 0.5` as "probably + a `.gif`" -#### english corpora +produced a network with about 87% accuracy -The english-1 corpus was obtained by manually scraping the first results from -a https://www.google.com/webhp?lr=lang_en search for "paris filetype:txt". +#### English corpora -The english-0 corpus was obtained by manually scraping the first results from -a https://www.google.com/webhp?lr=lang_fr search for "paris filetype:txt". +The [english-1](dlowe-aux-data/english-1) corpus was obtained by manually scraping the first results from +a search for "[paris +filetype:txt](https://www.google.com/search?q=paris+filetype%3Atxt&lr=lang_en&tbs=lr%3Alang_1en&sxsrf=APwXEdeHXyUYdUxCYQQDHmJhbHzX9aARSA%3A1683049834430&source=hp&ei=ak1RZJHUGN_DkPIP26OtkA8&iflsig=AOEireoAAAAAZFFbejA0Xfqoq__FXx--Ok0S6GQjnGnA&ved=0ahUKEwiRsZOcmdf-AhXfIUQIHdtRC_IQ4dUDCAo&uact=5&oq=paris+filetype%3Atxt&gs_lcp=Cgdnd3Mtd2l6EANQAFgAYN4DaABwAHgAgAE-iAE-kgEBMZgBAKABAqABAQ&sclient=gws-wiz)". -Results: +The [english-0](dlowe-aux-data/english-0) corpus was obtained by manually scraping the first results from +a search for "[paris +filetype:txt](https://www.google.com/search?q=paris+filetype%3Atxt&lr=lang_fr&tbs=lr%3Alang_1fr&sxsrf=APwXEddcsQ-gMhrqSUJo6omWFUl7jQMASg%3A1683049870736&source=hp&ei=jk1RZLevK_fKkPIPjbWN-AU&iflsig=AOEireoAAAAAZFFbnvExHGkcavB5H8F0xsLAWN2KfYFK&ved=0ahUKEwi3rrutmdf-AhV3JUQIHY1aA18Q4dUDCAo&uact=5&oq=paris+filetype%3Atxt&gs_lcp=Cgdnd3Mtd2l6EANQAFgAYLMDaABwAHgAgAE-iAE-kgEBMZgBAKABAqABAQ&sclient=gws-wiz)". - * using these corpora as a training set - * using several dozen additional text files (obtained by the same methods) - as a test set - * using the included "earlystop.pl" script, which stopped after 10000 - iterations. - * interpreting output of "> 0.5" as "probably english" and "< 0.5" as - "probably french" - * produced a network with 100% accuracy +##### Results: + +* Using these corpora as a training set; +* Using several dozen additional text files (obtained by the same methods) as a +test set; +* Using the included [earlystop.pl](earlystop.pl) script, which stopped after +10000 iterations; +* Interpreting output of `> 0.5` as "probably English" and `< 0.5` as "probably +French" + +produced a network with 100% accuracy. #### xor corpora -The xor-1 corpus consists of two files containing '01' and '10' respectively. +The [xor-1](dlowe-aux-data/xor-1) corpus consists of two files containing `01` +and `10` respectively. -The xor-0 corpus consists of two files containing '00' and '11' respectively. +The [xor-0](dlowe-aux-data/xor-0) corpus consists of two files containing `00` +and `11` respectively. -Results: +##### Results: - * using these corpora as a training set - * takes about 8000 iterations to learn xor to within a tolerance of <0.01 +Using these corpora as a training set takes about 8000 iterations to learn xor +to within a tolerance of `<0.01`. ### Limitations The program can't tell you anything meaningful about files with less than two -bytes in them (I'm looking at you, smr.c!) +bytes in them (I'm looking at you, [smr.c](/1994/smr/smr.c)!) You must include the trailing directory separator on training directories (this allows the program to be portable without wasting precious bytes on -figuring out how to concatenate directory and file names...) +figuring out how to concatenate directory and file names...). Serialized network files are only portable between systems with the same -floating-point representation and endianness. +[floating-point](https://en.wikipedia.org/wiki/Floating-point_arithmetic) +representation and [endianness](https://en.wikipedia.org/wiki/Endianness). -Making sure not to overfit the network to the training data is a bit of a -black art. I have enclosed 'earlystop.pl', a wrapper script that implements +Making sure not to +[overfit](https://en.wikipedia.org/wiki/Overfitting#Machine_learning) the network to the training data is a bit of a +black art. I have enclosed [earlystop.pl](earlystop.pl), a wrapper script that implements a simple 'early stopping' algorithm; other techniques are possible. Bad input (e.g. nonexistent files, non-numeric number of iterations, etc.) @@ -277,32 +304,27 @@ Leaks memory and file descriptors while processing files. Will crash and die horribly if it runs out of memory. -The Microsoft C compiler doesn't provide a dirent API, so to get this working -on a Windows system you'll need cygwin+gcc (tested) or a dirent compatibility +The Microsoft C compiler doesn't provide a `dirent` API, so to get this working +on a Windows system you'll need cygwin+gcc (tested) or a `dirent` compatibility library (untested, but they do exist). Backpropagation doesn't always converge: if you play with this long enough, you'll eventually have a training session that completely fails to converge. -### Obfuscation: +### Obfuscation -Zombies! (Since neural networks are modeled after BRAINS, ya know? And -corpus sounds a lot like corpse. And I have 4- and 7-year-old kids ;) - -Neural networks are interesting, and while the math isn't terribly difficult, +- [Zombies](https://en.wikipedia.org/wiki/Zombie)! (Since neural networks are +modeled after [BRAINS](https://en.wikipedia.org/wiki/Brain), ya know? And +corpus sounds a lot like corpse. And I have 4- and 7-year-old kids ;) ) +- Neural networks are interesting, and while the math isn't terribly difficult, their behavior is difficult to fully understand. - -Had some extra space in one of the major data structures, and it seemed a +- Had some extra space in one of the major data structures, and it seemed a shame to waste it. - -Similarly, I think three file pointers ought to be enough for anyone. - -Lots of magic numbers expressed in various ways. - -Random abuse of random C trivia. - -Some textual changes were made to maximize the classification of this program -by a network trained to recognize ioccc winners ;) +- Similarly, I think three file pointers ought to be enough for anyone. +- Lots of magic numbers expressed in various ways. +- Random abuse of random C trivia. +- Some textual changes were made to maximize the classification of this program +by a network trained to recognize [IOCCC winners](/winners.html) ;) ... but mostly zombies! diff --git a/2011/dlowe/try.me.sh b/2011/dlowe/try.me.sh new file mode 100755 index 000000000..add9107e1 --- /dev/null +++ b/2011/dlowe/try.me.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +make clobber dlowe || exit 1 + +./dlowe dlowe.c < dlowe-aux-data/ioccc-winlose-trained.net +./dlowe dlowe < dlowe-aux-data/ioccc-winlose-trained.net + +./dlowe xor-0/00 < dlowe-aux-data/xor-trained.net +./dlowe xor-0/11 < dlowe-aux-data/xor-trained.net +./dlowe xor-1/01 < dlowe-aux-data/xor-trained.net +./dlowe xor-1/10 < dlowe-aux-data/xor-trained.net + +./dlowe README.html < dlowe-aux-data/english-trained.net + +./dlowe dlowe-aux-data.tar.bz2 < dlowe-aux-data/png-trained.net + + diff --git a/2011/eastman/README.md b/2011/eastman/README.md index 85f50c492..ed08aecd1 100644 --- a/2011/eastman/README.md +++ b/2011/eastman/README.md @@ -1,7 +1,7 @@ # Best ball - Peter Eastman - +Peter Eastman + ## To build: @@ -23,6 +23,16 @@ Quit the program. Resize your terminal window. Run it again. ./eastman ``` +NOTE: to restore your cursor in your shell, try `reset`. + +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) tested this with +[macOS Ventura](https://www.apple.com/macos/ventura/) with the M1 chip for +the author (who tested [OS X 10.7 +(Lion)](https://en.wikipedia.org/wiki/OS_X_Lion) and [fedora +10](https://fedoraproject.org/wiki/Releases/10/FeatureList)) and reported that +it works fine. + + ## Judges' remarks: This round program will generate a classic spherical result! @@ -34,20 +44,21 @@ You might also want to turn off any scrollback history. The program will size itself to the initial geometry of your terminal. If you are ambitious, make the font really small and the window really -large for hi-rez graphics! +large for hi-res graphics! ## Author's remarks: This program uses ANSI graphics to recreate the classic Boing Ball demo from -the Commodore Amiga. See http://www.youtube.com/watch?v=-ga41edXw3A if you +the Commodore Amiga. See if you aren't familiar with it. Back in its day, this demo inspired lust and awe in geeks around the world. -The graphics are raytraced, with procedural textures on the ball and the back -wall. I did cheat a little to simplify the calculations: it uses a parallel -projection, but textures the back wall to look as if there were a floor being -viewed in perspective. The shadow is also just part of the texture, not an -actual raytraced shadow. +The graphics are +[raytraced](https://en.wikipedia.org/wiki/Ray_tracing_(graphics), with +procedural textures on the ball and the back wall. I did cheat a little to +simplify the calculations: it uses a parallel projection, but textures the back +wall to look as if there were a floor being viewed in perspective. The shadow +is also just part of the texture, not an actual raytraced shadow. This program automatically adapts to the size of the terminal it is running in, so try enlarging the window to get higher resolution. Don't resize while the @@ -59,12 +70,12 @@ To compile: cc -lm eastman.c ``` -Portability: +### Portability -It should be completely portable. I've tested with gcc on Mac OS X 10.7 and -Fedora 10. I would expect it to work in any Unix-like environment. +It should be completely portable. I've tested with gcc on Mac OS X 10.7 (Lion) +and Fedora 10. I would expect it to work in any Unix-like environment. -Obfuscation: +### Obfuscation I have merged expressions wherever possible, making extensive use of ternary operators, commas, return values of assignment operators, etc. The entire @@ -73,22 +84,22 @@ evaluations, is a single expression involving 41 operators. Variables are named alphabetically in the order they are declared. -The third argument to ioctl() should really be a "struct winsize", and I should -then look up the ws_row and ws_col fields, but that makes it way too obvious -what I'm doing there. Since a winsize just contains four unsigned shorts, I +The third argument to `ioctl()` should really be a `struct winsize`, and I should +then look up the `ws_row` and `ws_col` fields, but that makes it way too obvious +what I'm doing there. Since a `struct winsize` just contains four unsigned shorts, I replaced it with an array. And since all the values will be much less than -32767, I further simplified the type to just short[]. +`32767`, I further simplified the type to just `short[]`. A wonderful thing about ANSI graphics is that it produces nearly unintelligible code. Consider the printf spec to print a single space in a desired color: -"\x1B[%dm ". I could have done something to further obfuscate it, but it's +`"\x1B[%dm `. I could have done something to further obfuscate it, but it's already indistinguishable from line noise, so why bother? There are lots of other minor obfuscations to make the code less obvious. For -example, I could have written the outer loop as while(1), but why write a 1 -when I can calculate it from the return value of usleep() instead? And I could -have written usleep(80000), but usleep(79383) just looks so much better. And -so on. +example, I could have written the outer loop as `while(1)`, but why write a 1 +when I can calculate it from the return value of `usleep()` instead? And I could +have written `usleep(80000)`, but `usleep(79383)` just looks so much better. +And so on. ## Copyright and CC BY-SA 4.0 License: diff --git a/2011/fredriksson/README.md b/2011/fredriksson/README.md index 46ff0f03a..5c1c2ec15 100644 --- a/2011/fredriksson/README.md +++ b/2011/fredriksson/README.md @@ -1,7 +1,7 @@ # Most useful - Kimmo Fredriksson - +Kimmo Fredriksson + ## To build: @@ -28,18 +28,18 @@ will likely cause the program to dump core. ## Judges' remarks: -The author of this entry was making sure that it does not win the -"Best Short Program" award. On the outside, the program behaves -as an approximate grep. On the inside, it is a Burrows-Wheeler -transform decompressor that produces the source code of the actual -obfuscated approximate grep program and calls it. As an exercise, -try writing the compressor. +The author of this entry was making sure that it does not win the "Best Short +Program" award. On the outside, the program behaves as an approximate `grep`. +On the inside, it is a [Burrows-Wheeler +transform](https://en.wikipedia.org/wiki/Burrows-Wheeler_transform) decompressor +that produces the source code of the actual obfuscated approximate `grep` +program and calls it. As an exercise, try writing the compressor. ## Author's remarks: ### Approximate grep -Implements a variant of grep. +Implements a variant of `grep`. ### Usage @@ -49,8 +49,8 @@ To search regexp from file, do: ./fredriksson [-icvtnk#] regexp < file ``` -Pipes may not work, see the section Limitations. -The options `-i -c -v` and `-n` are the classic ones: +Pipes might not work, see the section Limitations. +The options `-i`, `-c`, `-v` and `-n` are the classic ones: * `-i` Ignore case. @@ -61,30 +61,36 @@ The options `-i -c -v` and `-n` are the classic ones: * `-n` Prefixes each printed line by its line number (only if `-c` was not given). -This version of grep recognizes two more options, not present in normal -grep implementations: +This version of `grep` recognizes two more options, not present in normal +`grep` implementations: * `-kN` Permit `N` insertions, deletions or mismatches of characters in the - matches (aka edit-distance). E.g. "obfuscated" matches "obfuscation" - with one deletion and two mismatches. Likewise, "obfuscate" and - "oversimplify" match with 7 edit operations. The default is `-k0` + matches (aka + [edit-distance](https://en.wikipedia.org/wiki/Edit_distance)). E.g. + "`obfuscated`" matches "`obfuscation`" + with one deletion and two mismatches. Likewise, "`obfuscate`" and + "`oversimplify`" match with 7 [edit + operations](https://en.wikipedia.org/wiki/Edit_distance#Formal_definition_and_properties). The default is `-k0` (i.e. exact match). -* `-t` Add local transpositions to the set of allowed edit-operations. - That is, "ab" matches "ba" with one transposition (swap), and - "obfuscated" matches "bofsuact" with three swaps and two insertions, +* `-t` Add local transpositions to the set of allowed + [edit-operations](https://en.wikipedia.org/wiki/Edit_distance#Formal_definition_and_properties). + That is, "`ab`" matches "`ba`" with one transposition (swap), and + "`obfuscated`" matches "`bofsuact`" with three swaps and two insertions, i.e. use `-tk5` to find this. -Of course, one could construct a standard regexp that matches the same +Of course, one could construct a standard +[regexp](https://www.regular-expressions.info) that matches the same patterns, but the problem is that such a regexp grows exponentially in -size when the number of allowed edit operations is increased. +size when the number of allowed [edit +operations](https://en.wikipedia.org/wiki/Edit_distance#Formal_definition_and_properties) is increased. This version does not recognize all regular expressions, but the following are allowed: -* Wild card: `.` (dot) matches any character. +* Wildcard: `.` (dot) matches any character. -* Bracket expression: list of charactres enclosed by `[` and `]`, +* Bracket expression: list of characters enclosed by `[` and `]`, matches any single character in the list. * Range expression: two characters separated by hyphen and enclosed in @@ -92,7 +98,7 @@ following are allowed: two characters (inclusive). E.g. `[a-d]` is the same as `[abcd]`. The special characters must be escaped, if they are to be taken -literally (i.e. use e.g. `\.` to match period). You might want to protect +literally (e.g. `\.` to match period). You might want to protect these with `'`, i.e. use `'foo\[bar'` instead of `foo\[bar`. If you want to use the literal `-` in bracket expression, protect that too (`\-`), otherwise this is not needed. Note that the syntax differs from standard @@ -101,13 +107,18 @@ expressions by putting `]` as the first character, and putting `-` last. ### Other uses -* You can use this in place of cat. Just say +* You can use this in place of [cat](https://en.wikipedia.org/wiki/Cat_(Unix)). +Just say - ./fredriksson -k3 cat < file +```sh +./fredriksson -k3 cat < file +``` -* Like with cat, you can append line numbers too: +* Like with `cat`, you can append line numbers too: - ./fredriksson -nk3 cat < file +```sh +./fredriksson -nk3 cat < file +``` ### Other features @@ -118,13 +129,13 @@ expressions by putting `]` as the first character, and putting `-` last. * It may consume huge amounts of memory, and a stack overflow may occur. This results in Segmentation fault (or the equivalent of your favorite system, such as Bus error). This is a feature, that can be used to detect - overly long lines in the input file, such as checking the lenght of one + overly long lines in the input file, such as checking the length of one liners in IOCCC entries, just adjust your stack size to a suitable - threshold, and search for "ioccc", with option `-vk5`. + threshold, and search for "`ioccc`", with option `-vk5`. ### Limitations and remarks -* Using warning options (such as -Wall) when building gives a lot of warning, +* Using warning options (such as `-Wall`) when building gives a lot of warning, such as `suggest parentheses around '&&' within '||'`, `value computed is not used`, `implicit declaration of function 'putchar'`, `implicit declaration of function 'getchar'`, `control reaches end of non-void @@ -136,7 +147,7 @@ expressions by putting `]` as the first character, and putting `-` last. i.e. pipes may or may not work. If you want to count only (`-c` option), then this shouldn't be an issue. -* The total lenght of the (preprocessed) pattern is at most +* The total length of the (preprocessed) pattern is at most `sizeof(long)*CHAR_BIT`. That does not count things like bracket expressions or escape chars, that is, the pattern `'a[bcd]e\.f'` is 5 chars long, not 10 chars. That does not mean that the matched substring in the standard @@ -144,7 +155,7 @@ expressions by putting `]` as the first character, and putting `-` last. longer. However, no assumptions are made for `sizeof(long)`. In fact, you can easily use `long long` instead, -* Depending on the file, may require a lot of stack space. If the +* Depending on the file, it might require a lot of stack space. If the program segfaults (because of this), say ulimit -s unlimited @@ -155,7 +166,7 @@ expressions by putting `]` as the first character, and putting `-` last. handle this just fine even in C89 mode, though. * The code should be reasonably portable, it assumes standard ASCII codes - for each char, and that a C compiler is on $PATH; the latter is hard coded + for each char, and that a C compiler is on `$PATH`; the latter is hard coded to be 'gcc', but any compiler would work, provided that it supports C99, or long lines as an extension. This code has been tested on: @@ -173,7 +184,8 @@ expressions by putting `]` as the first character, and putting `-` last. ### Obfuscations (a.k.a. spoilers...) * The initialized char array includes the source code of the real program, - as well as its name and commands to build and run it, all Burrows-Wheeler + as well as its name and commands to build and run it, all + [Burrows-Wheeler](https://en.wikipedia.org/wiki/Burrows-Wheeler_transform) -transformed, then run-length-encoded with unary coding. The main program extracts and builds that, and then calls it. More precisely, the command to build is @@ -189,14 +201,12 @@ expressions by putting `]` as the first character, and putting `-` last. from the submitted entry.) * The code demonstrates several useful programming paradigms, such as - - recursion to remove all loops - - sub routines (`main()` contains several logical sub routines, + - subroutines (`main()` contains several logical subroutines, selected by the first argument) - function pointers * Algorithmically, it incorporates the following - - (inverse) Burrows-Wheeler transform (used also e.g. in bzip2) - data compression (really expansion :-), run-lenght-encoding, unary coding (this is why it is expansion rather than compression) @@ -208,10 +218,9 @@ expressions by putting `]` as the first character, and putting `-` last. - self extracting, compiling and running code * As a C program, it demonstrates that - - a C subset without reserved words is complete enough, (excluding data type specific things (`int`, `char`, `void` ...)) - - only letters are needed (i.e. the digits 0-9 are not) + - only letters are needed (i.e. the digits `0-9` are not) - only one statement is enough to code any program (plus variable definitions) - white space has other uses than just indenting the code @@ -219,8 +228,8 @@ expressions by putting `]` as the first character, and putting `-` last. * It also shows the power of boolean logic and bitwise arithmetic. * This is the first (?) entry in the history of IOCCC, that cannot be - totally un-obfuscated by the author. This is due to the clever choice of - the actual algorithm, that is obfucated by nature, and it is an open + totally de-obfuscated by the author. This is due to the clever choice of + the actual algorithm, that is obfuscated by nature, and it is an open research problem whether a simpler algorithm exists, with the same time complexity. @@ -234,12 +243,12 @@ expressions by putting `]` as the first character, and putting `-` last. ./fredriksson -ck0 [0-9] < fredriksson.c - This should print 1, as there is a number '3' in the char array (only). + This should print 1, as there is a number `3` in the char array (only). You can also try ./fredriksson -ck0 [0-9] < ag.c - after running fredriksson at least once (since this generates that + after running `fredriksson` at least once (since this generates that `ag.c` file), and this should print 0. * The source code is best viewed with cat (or using the program itself), @@ -247,7 +256,7 @@ expressions by putting `]` as the first character, and putting `-` last. One reason for this is that the code builds (some of the) constant values from string literal `"\b"`, except that the backspace `\b` is not - escaped like that, the source uses the raw ascii value (010 octal) instead. + escaped like that; the source uses the raw ascii value (010 octal) instead. Thus when viewing with cat or something, that backspace erases the leading quotation mark. Makes it appear uncompilable, and it is: if you copy-paste the cat output from terminal to some editor, save it, the result would not diff --git a/2011/goren/README.md b/2011/goren/README.md index 07e96e685..4c929f1b2 100644 --- a/2011/goren/README.md +++ b/2011/goren/README.md @@ -1,7 +1,7 @@ # Most artistic - Uri Goren - +Uri Goren + ## To build: @@ -15,6 +15,12 @@ make echo "some text" | ./goren ``` +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed this for macOS. +Before the fix it segfaulted. It worked fine under linux. After fixing it it was +noticed that the author stated it does not work for 64-bit so it was then tested +as a 32-bit binary (linux) and 64-bit binary (linux, macOS) and both work. It +was fixed by changing some `int`s to `long`s. Thank you Cody! + ## Try: ```sh @@ -29,18 +35,24 @@ In the words of [René François Ghislain Magritte Magritte](http://en.wikipedia One may ask the surrealist question: - echo 'If | is just a representation of a pipe, then how can data stuff it?' | ./goren +```sh +echo 'If | is just a representation of a pipe, then how can data stuff it?' | ./goren +``` However if one takes a firm stand and declares: - echo '| is just a representation of a pipe because I say so! So stuff it!' | ./goren +```sh +echo '| is just a representation of a pipe because I say so! So stuff it!' | ./goren +``` something happens! Why? ## Author's remarks: -This program was written in homage to Rene Magritte's picture "La -trahison des images" (The Treachery of Images). +This program was written in homage to [Rene +Magritte](http://en.wikipedia.org/wiki/Rene_Magritte)'s picture ["La +trahison des images" (The Treachery of +Images)](https://en.wikipedia.org/wiki/The_Treachery_of_Images). In order to show my unconditional admiration of this work, I avoided using conditions. @@ -50,8 +62,8 @@ a pipe. But what IS a pipe? This program tries to provide an answer. Magritte's [test for pipes](http://en.wikipedia.org/wiki/The_Treachery_of_Images) is: - The famous pipe. How people reproached me for it! And yet, could - you stuff my pipe? No, it's just a representation, is it not? +> The famous pipe. How people reproached me for it! And yet, could +> you stuff my pipe? No, it's just a representation, is it not? Accordingly, this program only approves pipes which can be used for stuffing data. @@ -60,14 +72,14 @@ One thing I tried to achieve is condition free programming. Many have noted that conditions make the code harder to read and understand. A good example would be: -[Brent Burley's 2004 IOCCC winner](http://www.ioccc.org/years.html#2004_burley) +[Brent Burley's 2004 IOCCC winner](/2004/burley/burley.c). -That entry omits conditional statements such as "if" and "while". +That entry omits conditional statements such as `if` and `while`. His achievement in improving clarity by omitting conditions is impressive, but I think it can be taken further, in two ways. -First, conditional operators, such as ?:, && and ||, can be thrown -away. Second, using setjmp and longjmp, which are unfortunately +First, conditional operators, such as `?:`, `&&` and `||`, can be thrown +away. Second, using `setjmp` and `longjmp`, which are unfortunately not in common use, might make it difficult for a novice programmer to understand the code without referring to the man page. diff --git a/2011/goren/goren.c b/2011/goren/goren.c index c8c6d4776..48fd7af1e 100644 --- a/2011/goren/goren.c +++ b/2011/goren/goren.c @@ -1,20 +1,20 @@ -typedef unsigned char t;t*F="%c",l[]="|\\/=_ \n](.\0(),*(.(=(}*.)[[*.",N='\n',* -r;typedef(*H)();extern H Ar;Q(a){return(a|-a)>>31;}H S(c,a){return(H)(a&~c|(int -)Ar&c);}extern t*ist;V(t*u){*u^=*u&2^(*u>>7)*185;}Z(t*u,t n){*u-=n;}e(t c,H h){ -R(h,Q(* r^c));} -I(){r=l +7-4*Q( -getchar ()^*l); -}R(H h, int c){Ar=S -(c,h);- main() ;}P(){r -++;}z() { O(&N);} -O(t*c){ printf( F,+*c); -}T(){r= "This is not a function\n" ;}w(U){ -U=Z(r,8 ); r-=~Q(* -r/8-4); return 0; }M(){r= -ist-68; } h(){t G -=r[1]-r [2]^*r; -G^=30;V (&G);e( -0,(O(&G ),P(P(* -r++)),z));}g(){M();R(h,0);}f(){P(O(r));e('f',g);}p(){P();e('a',f);}d(){P(O(r)); -e('n',p);}c(u){u=r[-2];T(Ar=d);R(f,Q(u^'"'));}n(){e(w(O(l+*r%8)),c);}a(){I();R( -n,0);}main(){S(Q(Ar),a)();}H Ar;t*ist="Rene Magritte"-(1898-1967); +typedef unsigned char t;t*F="%c",l[]="|\\/=_ \n](.\0(),*(.(=(}*.)[[*.",N='\n',* +r;typedef(*H)();extern H Ar;Q(a){return(a|-a)>>31;}H S(long c,long a){return(H)(a&~c|(long +)Ar&c);}extern t*ist;V(t*u){*u^=*u&2^(*u>>7)*185;}Z(t*u,t n){*u-=n;}e(t c,H h){ +R(h,Q(* r^c));} +I(){r=l +7-4*Q( +getchar ()^*l); +}R(H h, int c){Ar=S +(c,h);- main() ;}P(){r +++;}z() { O(&N);} +O(t*c){ printf( F,+*c); +}T(){r= "This is not a function\n" ;}w(U){ +U=Z(r,8 ); r-=~Q(* +r/8-4); return 0; }M(){r= +ist-68; } h(){t G +=r[1]-r [2]^*r; +G^=30;V (&G);e( +0,(O(&G ),P(P(* +r++)),z));}g(){M();R(h,0);}f(){P(O(r));e('f',g);}p(){P();e('a',f);}d(){P(O(r)); +e('n',p);}c(u){u=r[-2];T(Ar=d);R(f,Q(u^'"'));}n(){e(w(O(l+*r%8)),c);}a(){I();R( +n,0);}main(){S(Q(Ar),a)();}H Ar;t*ist="Rene Magritte"-(1898-1967); diff --git a/2011/hamaji/README.md b/2011/hamaji/README.md index 7abdcdef3..6e9c344e8 100644 --- a/2011/hamaji/README.md +++ b/2011/hamaji/README.md @@ -1,7 +1,7 @@ # Best solved puzzle - Shinichiro Hamaji - +Shinichiro Hamaji + ## To build: @@ -30,29 +30,29 @@ make ## Judges' remarks: This program solves "Nonogram", which also known as "Paint by Numbers": - - +. This entry roar as the Year of the Dragon: A year considered some to be good luck. Well it was certainly true that the IOCCC was lucky to get such a fine submission! The source code is a solution to a Paint by Numbers puzzle when you -paint by C. Try your hand at solving a few of the other .nono +paint by C. Try your hand at solving a few of the other `.nono` files and then compare your solution with this program! -NOTE: NONOGRAM (r) is a registered Trademark and is used with permission. - See http://nonogram.com/ for more information. +NOTE: NONOGRAM (r) is a registered Trademark and is used with permission. See + for more +information. ## Author's remarks: The format of the input files are as same as this site: +. - - -For example, for a simple problem which shows a glider of [conway's -lifegame](http://en.wikipedia.org/wiki/Conway's_Game_of_Life). +For example, for a simple problem which shows a glider of [Conway's +Game of Life](http://en.wikipedia.org/wiki/Conway's_Game_of_Life): +``` 1 . 112 @@ -61,8 +61,11 @@ lifegame](http://en.wikipedia.org/wiki/Conway's_Game_of_Life). 1 X 3 XXX +``` + the input should be +``` 1 1 3 @@ -70,63 +73,76 @@ the input should be 1 1.1 2 +``` The width and the height of an input puzzle should be less than or equal to 60. -When this solver finds the problem has no solution, it prints "invalid". +When this solver finds the problem has no solution, it prints "`invalid`". This means the problem is indeed broken. For example, this happens for an input like +``` 2 - 2 +``` -When this solver cannot find a solution, it prints "failed". This +When this solver cannot find a solution, it prints "`failed`". This failure can happen when the problem has more than one solution or the solver cannot solve the input problem. Here is an example input of the former: +``` 1 1 - 1 1 +``` There are two solutions: +``` 11 1 X 1 X +``` and +``` 11 1 X 1 X +``` ### Detail -Solving Nonogram is known NP-complete, so we cannot make a solver -which solves all puzzles. However, we can write a solver which solves -most problems solvable by humans. There are a bunch of ways to write -such programs. The two most obvious approaches are: +Solving Nonogram is +[NP-complete](https://en.wikipedia.org/wiki/NP-completeness), so we cannot make +a solver which solves all puzzles. However, we can write a solver which solves +most problems solvable by humans. There are a bunch of ways to write such +programs. The two most obvious approaches are: 1. Check all possible solutions with backtracking. 2. Implement all techniques which humans use. The former, brute-force approach is easy to implement. However, it works only for smaller problems (width and height should be at most 30 -or so). Similarly, using generic probabilistic metaheuristics such as -simulated annealing doesn't work for big problems. +or so). Similarly, using generic probabilistic +[metaheuristics](https://en.wikipedia.org/wiki/Metaheuristic) such as +[simulated annealing](https://en.wikipedia.org/wiki/Simulated_annealing) doesn't +work for big problems. - +See: . By its definition, the latter works for all human-solvable problems. The issue of the latter approach is this kind of programs -tends to be lengthy. This approach still requires some recursions. The +tends to be lengthy. This approach still requires some +[recursions](https://en.wikipedia.org/wiki/Recursion). The most difficult problems which are considered human-solvable may require some "guesses". For this kind of problems, we need to assume a cell is a space or a box, go ahead some steps with simple methods, @@ -134,19 +150,19 @@ mark the tried cell as a box (or a space if we assumed the tried cell is a box) if a contradiction is found. My program uses an approach like "Set based solver" introduced in -[http://www.haskell.org/haskellwiki/Nonogram](http://www.haskell.org/haskellwiki/Nonogram) . -This should be equivalent to the combinations of simple methods (no -advanced reasoning with guess). My solver also runs non-recursive -guess for each undetermined cells. So, my program should be able to -solve most human-solvable problems (assuming humans cannot execute -deeper recursions). +. This should be equivalent +to the combinations of simple methods (no advanced reasoning with guess). My +solver also runs a non-recursive guess for each undetermined cells. So, my +program should be able to solve most human-solvable problems (assuming humans +cannot execute deeper recursions). ### Obfuscation -First of all, as you see, my program looks like a nonogram puzzle -which results a dragon. This puzzle is "dragon.nono" in this -directory. Note that whitespaces in character literals, a string -literal, and around the last comment are considered as a boxed cell. +First of all, as you see, my program looks like a nonogram puzzle which results +in a [dragon](https://www.draconika.com/what). This puzzle is +[dragon.nono](dragon.nono) in this directory. Note that whitespaces in character +literals, a string literal, and around the last comment are considered as a +boxed cell. My program is based on bit operations for speed. Many values are stored using negative logic (0 means on and 1 means off) to utilize @@ -162,22 +178,22 @@ with the well obfuscated code. ### Portability -This program uses two C99 features. One line comments and "long long". -GCC's "-ansi -pedantic" check should pass: +This program uses two C99 features. One line comments and `long long`. +GCC's `-ansi -pedantic` check should pass: ```sh cc -ansi -pedantic -std=c99 hamaji.c ``` -I checked my program with gcc-4.6.2 on linux, llvm-gcc-4.2 on mac, and -clang-3.0 on mac. +I checked my program with gcc-4.6.2 on linux, llvm-gcc-4.2 on Mac, and +clang-3.0 on Mac. -Note that the behavior of scanf differs on linux and mac, but this +Note that the behavior of `scanf()` differs on linux and mac, but this program supports both semantics. -This program should not depend on sizeof(int), sizeof(void*), ASCII, -memory layout, undefined evaluation order (e.g., a[i++]=i), etc. -This program won't work if the size of long long literal is less than 8. +This program should not depend on `sizeof(int)`, `sizeof(void*)`, ASCII, +memory layout, undefined evaluation order (e.g., `a[i++]=i`), etc. +This program won't work if the size of `long long` literal is less than 8. By grepping the source code of gcc ```sh @@ -186,25 +202,26 @@ grep LONG_LONG_TYPE_SIZE gcc/config/*/* I found long long may be 32bit integers only on AVR. -### A few more +### A few more things -This code is considered as a new year's postcard in Japan. We chose -the dragon because 2012 is the year of dragon. - - +This code is considered as a [new year's postcard in +Japan](http://en.wikipedia.org/wiki/Japanese_New_Year#Postcards). We chose +the dragon because 2012 is the [year of +dragon](https://japanesezodiac.com/japanese-year-of-the-dragon). The second author wrote the picture, and the first author did everything else. -The dragon.nono, samurai.nono, and penguin.nono was written by the -second author. The soccer.nono was from a wikipedia entry. This file -is important because it requires some guesses. The random.nono file -was randomly generated. The codegolf.nono and face.nono have borrowed -from this site: +The [dragon.nono](dragon.nono), [samurai.nono](samurai.nono), and +[penguin.nono](penguin.nono) were written by the +second author. The [soccer.nono](soccer.nono) was from a wikipedia entry. This file +is important because it requires some guesses. The [random.nono](random.nono) file +was randomly generated. The [codegolf.nono](codegolf.nono) and +[face.nono](face.nono) were taken from +. - - -You can reproduce dragon.nono from hamaji.c using c2nono.pl: +You can reproduce [dragon.nono](dragon.nono) from [hamaji.c](hamaji.c) using +[c2nono.pl](c2nono.pl): ```sh perl c2nono.pl hamaji.c | ./hamaji diff --git a/2011/hou/README.md b/2011/hou/README.md index e7322bb4c..fb2adefba 100644 --- a/2011/hou/README.md +++ b/2011/hou/README.md @@ -1,7 +1,7 @@ # Best self documenting program - Hou Qiming - +Hou Qiming + ## To build: @@ -12,19 +12,23 @@ make ## To run: ```sh -./hou 'a calculator expression -- see the C Code for details' +./hou 'expression' ``` ## Try: ```sh -./hou 11/26+222/31 +./hou '11/26+222/31' ./hou 'log((21701-19937)-(23209-21701))/log(2)' ./hou 'sin(1.5708)+0.04321+log(sqrt(exp(1*1*1)))+(1+2*3)-0.4-0.6+(4+6)*(2-1+2*3)-tan(0.785398)+2*10/3*6*sqrt(16/2/2)*10+10000-1000' + +./hou 'a calculator expression -- see the C Code for details' ``` +What does the last one mean? + ## Judges' remarks: This self-documenting scientific calculator compiles clean with no @@ -33,7 +37,7 @@ warnings under the most strict pedantic mode of gcc and clang. The first example, along with the correct result appears in the source code. What does it mean? -The calculator obeys the precendence rules and allows parenthesis, +The calculator obeys the precedence rules and allows parenthesis. ```sh ./hou '1+2*3' @@ -54,24 +58,28 @@ Comments would almost be redundant. :-} ### The ASCII art is valid C code -Not just fancy formatted comment removed by the C Pre-processor +... and not just fancy formatted comment removed by the C Pre-processor. ### The only multi-byte strings are format strings -The code does not contain some simple string-encoded lookup table for calculator operations. +The code does not contain some simple string-encoded lookup table for calculator +operations. ### Example input and output in the source -The example input and output in the C code is significant. Can you find out why? +The example input and output in the C code is significant. Can you find out +why? ### The button layout -The button layout in the C code is significant ... not just a nice looking layout. +The button layout in the C code is significant ... not just a nice looking +layout. ### input parsing -The parser is functionally equivalent to a normal arithmetic parser for all valid inputs. -For another fun challenge: try to determine how it parses the command line argument. +The parser is functionally equivalent to a normal arithmetic parser for all +valid inputs. For another fun challenge: try to determine how it parses the +command line argument. ## Author's remarks: @@ -81,32 +89,34 @@ This program is designed to be self-documenting. It doesn't just provide an example command line. It also provides the expected output and illustrates all supported functionality using embedded ASCII art. -- A few line numbers are significant and careless beautification will break the program. +- A few line numbers are significant and careless beautification will break the +program. - The entire ASCII art is valid code. The preprocessor won't remove any part of it. - The only strings longer than 1 byte are printf/sscanf format strings, even - after preprocessing. No string-encoded lookup table is used. -- The example input and its expected output are both algorithmically significant. +after preprocessing. No string-encoded lookup table is used. +- The example input and its expected output are both algorithmically +significant. - The button layout is also significant. -- The actual syntax being parsed is not the obvious, despite being - functionally equivalent for all correct inputs. +- The actual syntax being parsed is not that obvious, despite being functionally +equivalent for all correct inputs. ### Portability -- This program requires "argv" to point to writable memory. It doesn't require - the actual argv strings to be writable, though. +- This program requires `argv` to point to writable memory. It doesn't require +the actual argv strings to be writable, though. - This program requires ASCII. -- This program doesn't work with %e style numbers like "1e-4". +- This program doesn't work with `%e` style numbers like `1e-4`. - Some seemingly redundant code works to eliminate warnings and evade a gcc bug. ### Spoilers -The parser parses function names, substraction, and division as single-letter +The parser parses function names, subtraction, and division as single-letter unary operators. A bitmask encoded hash table is used to check no-ops/digits and another hash function maps the ASCII to a function ordinal, which is then executed by the button panel. -Both hash functions are found using a separate search program. Another program -is used to find a way to format one hash function as example input such that +Both hash functions were found using a separate search program. Another program +was used to find a way to format one hash function as example input such that it produces something resembling the bitmask hash table as part of its output. ## Copyright and CC BY-SA 4.0 License: diff --git a/2011/konno/README.md b/2011/konno/README.md index c0abacf43..a005b64fd 100644 --- a/2011/konno/README.md +++ b/2011/konno/README.md @@ -1,8 +1,8 @@ # Best one liner - Taketo Konno - Tokyo, Japan - +Taketo Konno +Japan + ## To build: @@ -13,7 +13,7 @@ make ## To run: ```sh -./konno just_a_single_argument_of_lower_case_letters +./konno lower_case_word ``` ## Try: @@ -47,8 +47,8 @@ This program ignores non-lower case letters. ### Obfuscation -* "for" is not used. -* A part of program is encrypted. +* `for` is not used. +* A part of the program is encrypted. ## Copyright and CC BY-SA 4.0 License: diff --git a/2011/richards/Makefile b/2011/richards/Makefile index 493115069..1ead51cb3 100644 --- a/2011/richards/Makefile +++ b/2011/richards/Makefile @@ -61,11 +61,11 @@ CDEFINE= # Include files that are needed to compile # -CINCLUDE= +CINCLUDE= -include stdlib.h -include string.h -include stdio.h -include ctype.h -include sys/mman.h -include setjmp.h # Optimization # -OPT= -O3 +OPT= # Default flags for ANSI C compilation # diff --git a/2011/richards/README.md b/2011/richards/README.md index 66262cd3c..28fbef457 100644 --- a/2011/richards/README.md +++ b/2011/richards/README.md @@ -1,7 +1,7 @@ # Most surprisingly portable - Gregor Richards - +Gregor Richards + ## To build: @@ -21,6 +21,9 @@ make echo '10 9 8 7 6 5 4 3 2 1*p*p*p*p*p*p*p*p*p' | ./richards ``` +NOTE: this entry does not work in macOS. See [bugs.md](/bugs.md) for more +details. + ## Judges' remarks: Oh no, yet another dc-style calculator? (see 2000/dlowe using an embedded Perl @@ -34,7 +37,7 @@ What would you do to prove or disprove his claim without attempting to unravel t This is an implementation of the classic UNIX dc command, the reverse-polish calculator. Actually it's a pretty bad implementation, since it only implements 32-bit integers (well, sizeof(int)-sized integers). It only implements the -commands +, -, *, /, p (only for numbers), register stacks, macros and +commands `+`, `-`, `*`, `/`, `p` (only for numbers), register stacks, macros and comparisons. Wow, you'd think I could've done better in 2K of code. OH! I forgot to mention! It's a JIT. @@ -48,19 +51,19 @@ integers are at least 32-bit. You will probably get warnings while compiling the code. In particular: * If your system requires the inclusion of alloca.h to use alloca, use the - compile flag -DAH - * If your system cannot use mmap, use the compile flag -DNM + compile flag `-DAH`. + * If your system cannot use mmap, use the compile flag `-DNM`. * I don't include any headers I don't strictly need to, so you'll get warnings - about (at least) memcpy, isdigit, atoi, calloc, malloc and alloca if you - didn't use -DAH. - * GCC likes to complain about while (a = b) (assignments as a condition). - * I don't return from main, even though it's declared to return int. + about (at least) `memcpy()`, `isdigit()`, `atoi()`, `calloc()`, `malloc()` + and `alloca()` if you didn't use `-DAH`. + * GCC likes to complain about `while (a = b)` (assignments as a condition). + * I don't return from `main()`, even though it's declared to return int. Platforms on which all known/tested optimization levels work with no additional flags: - * gcc 4.6.2 + x86[_64] + GNU/Linux, Mac OS X or Windows - * clang 2.9-16 + x86[_64] + GNU/Linux or Mac OS X + * gcc 4.6.2 + x86[\_64] + GNU/Linux, Mac OS X or Windows + * clang 2.9-16 + x86[\_64] + GNU/Linux or Mac OS X * tcc 0.9.25 * gcc 4.4.5 + alpha, arm, mips[el], powerpc[64], s390x (IBM zSeries) * gcc 4.1.3 + vax + NetBSD @@ -68,7 +71,7 @@ flags: Platforms which work but not at all optimization levels or needing special flags: - * owcc 1.9 + x86 + Windows: Needs -DNM -DAH -fno-stack-check + * owcc 1.9 + x86 + Windows: Needs `-DNM -DAH -fno-stack-check` * gcc 4.4.5 + sh4: -O0 works, higher optimization levels don't work for unknown reasons. ## Copyright and CC BY-SA 4.0 License: diff --git a/2011/richards/richards.c b/2011/richards/richards.c index cc74c5a6b..744d32f9b 100644 --- a/2011/richards/richards.c +++ b/2011/richards/richards.c @@ -24,11 +24,11 @@ #define H 9<<16 #define I case #define J(i) calloc(i,1) -#define W(c) e=(k*)memcpy(e,x[(u)c],y[(u)c])+y[(u)c]; +#define W(c) e=(o*)memmove(e,x[(u)c],y[(u)c])+y[(u)c]; #define N break; I q char k; q void o; -q int u; +q unsigned long u; q o(*f) (vo o *); q struct { u *a, **R, *m, h, c; @@ -43,7 +43,7 @@ u sk[H]; k *w; o *x[H]; u y[H]; -k *j, *e; +f *j, *e; u l=256; o g(u v) { @@ -123,15 +123,15 @@ o T() o rd(u v) { - k *a = 0, **b = &a, **c = b + 32; + o *a = 0, **b = &a, **c = b + 24; x[v] = w; - for (; b < c && (*b < w || *b > (k *) T || *b == (k *) (long) v); b++); + for (; b < c && (*b < (o *)w || *b > (o *) T || *b == (long) v); b++); if (b == c) { jmp_buf *j = alloca(sizeof(*j)); setjmp(*j); rd(v); } else { - y[v] = *b - w; + y[v] = *b - (o*)w; w = *b; } } @@ -146,7 +146,7 @@ o re(vo k * rec) } F(d) M--; *M /= M[1]; -} F(p) printf("%d\n", *M); +} F(p) printf("%lu\n", *M); } F(x) u n = *M--; if (!S j[n]) @@ -165,7 +165,7 @@ lx(d); o *lib1[] = { T, T, T, T, T } ; o *lib2[] = { T, ld, lp, lx, l1 } ; -u main() +int main() { u i; k *b; @@ -192,7 +192,7 @@ u main() #if NM malloc(H); #else - mmap(0, H, -1, MAP_PRIVATE | MAP_ANON, -1, 0); + mmap(NULL, H, -1, MAP_ANON | MAP_PRIVATE, -1, 0); #endif while (b = fgets(malloc(999), 999, stdin)) ((f) K(b, d)) (d); diff --git a/2011/toledo/README.md b/2011/toledo/README.md index 8f6f5193d..eb60d51b5 100644 --- a/2011/toledo/README.md +++ b/2011/toledo/README.md @@ -1,11 +1,9 @@ # Best non-chess game - Oscar Toledo G. - Av. Sta. Cruz del Monte 9-304 - Cd. Satelite. Edo. de Mexico. - CP. 53110. Mexico. - - +Oscar Toledo G. +Mexico + + ## To build: @@ -19,7 +17,8 @@ make ./toledo ``` -NOTE: This requires X11 to run or modifications to use layer.c on Windows. +NOTE: This requires X11 to run or modifications to use [layer.c](layer.c) on +Windows (see below). ## Try: @@ -30,7 +29,7 @@ echo "Do or do not. There is no try." ## Judges' remarks: This two player game uses X11. The control keys can be configured by -modifying the A,B,C and D macros at compilation. +modifying the `A`, `B`, `C` and `D` macros at compilation. After a quick splash screen the objective should be clear. There are Red, Green and Cyan tanks. A larger window can be made by altering @@ -47,6 +46,7 @@ you ought to be able to compile and run this program on Windows. ## Author's remarks: +``` /=========\ \==\ /==/ || || || /====\ |\/=\ || //==\ ==\ |=\ @@ -54,6 +54,7 @@ you ought to be able to compile and run this program on Windows. || || //===| || || ||=// \\=\\ ==/ |=/ || || || || || || || \\ || User's \===/ \\==// || || || \\ \==// Manual +``` This is a color X11 3D tank-game for two players, just compile and run it without arguments. @@ -75,7 +76,7 @@ extra points. When only one tank remains on the field, the level will advance. Don't forget to destroy the aqua tank. -The playground is surrounded by mountains and each level is +The battleplayground is surrounded by mountains and each level is filled with random obstacles (pyramids and cubes). The bars show players energy and score, each bar shows energy @@ -100,8 +101,8 @@ Keys for player 2: > Note: Numeric keys don't work. -If you don't like the keys assignment, you can change it on the -the makefile. +If you don't like the keys assignment, you can change it in the +Makefile. ### PARENTAL ADVISORY WARNING: @@ -112,7 +113,7 @@ Not really, just kidding :D ### PLATFORMS TESTED: -* openSuSE 10.2 x86-32, X11R6 1024x768 32-bits color. +* openSUSE 10.2 x86-32, X11R6 1024x768 32-bits color. * Fedora Core 8 x86-64, X11R6 1280x1024 32-bits color. * Fedora Core 11 x86-64, X11R6 1024x768 32-bits color. * Fedora Core 14 x86-64, X11R6 1024x768 32-bits color. @@ -121,11 +122,11 @@ Not really, just kidding :D * Multiplayer out of the box. * Totally self-contained, no external files. -* Fast-furious action at 29.97 frames per second. +* Fast-and-furious action at 29.97 frames per second. * Just as the movies, 16:9 aspect-ratio. * Beautiful mountains landscape plus horizon line :) * Tanks and bullets exploding as wires with weird physics. -* Tanks backoff when firing. +* Tanks back off when firing. * There is an infinite number of levels. * Always different levels. * Animated intro. @@ -133,27 +134,24 @@ Not really, just kidding :D ### FEATURES THAT PROGRAMMERS WILL FIND APPEALING: -* Works both with x86-32 and x86-64 processors. +* Works both with 32 and 64-bit CPUs. * Double buffered, portable to any X11 with 24/32-bit color. -* Memory-hungry as must be any 3-D program, uses a 256 MB - array. -* Total and absolute irreverent coding style, so it generates - a lot of warnings when compiled. -* It can take several minutes to compile (known culprits: - Fedora Core 11-14 on x86-64 512 MB) -* It is written in the only true C: K&R, and no, it not means +* Memory-hungry as must be any 3D program; uses a 256 MB array. +* Total and absolute irreverent coding style, so it generates a lot of warnings + when compiled. +* It can take several minutes to compile (known culprits: Fedora Core 11-14 on + x86-64 512 MB). +* It is written in the only true C: K&R, and no, that doesn't mean Katherine & Rose. -* Vectorial scalable graphics, do you want a bigger - playfield? change variables M & N. -* Half of the program is formatted as 3-D cube, view with - Tabs at 8 columns and a square font. -* The other half of the program is unprintable source code, - so no typing from paper, you have to write a converter of - tabs and formfeeds to its C escaped forms. -* No text, so this program can be used and understood easily - on any country. -* This program is highly ecologic, it sleeps when it is not - doing anything. +* Vectorial scalable graphics, do you want a bigger viewport? Change variables M + `&` `N`. +* Half of the program is formatted as 3D cube. View with tabs at 8 columns and a + square font. +* The other half of the program is unprintable source code, so no typing from + paper, you have to write a converter of tabs and form-feeds to its C escaped + forms. +* No text, so this program can be used and understood easily in any country. +* This program is highly ecological, it sleeps when it is not doing anything. * Virtual world with its own physics laws. * When closing the window it will show an X11 error :P @@ -162,9 +160,10 @@ Not really, just kidding :D * Loop code included inside loop test. * Function arguments used as variables. * Operators used freely. -* Precalculated values to save bytes. -* Uses the +++, +- and *+ undocumented C operators :P +* Pre-calculated values to save bytes. +* Uses the `+++`, `+-` and `*+` undocumented C operators :P +``` ....,,,,---++++++--,,.. .,,,....... .$@@@@@@@@@@@@$$@@@@@@@@@@@@@@#+ @@ -187,53 +186,51 @@ Not really, just kidding :D ..,+++=+-,.. .@. +=+ .,-+++++,@@== +``` + ### THE HISTORY OF THIS PROGRAM: When I started working on this program, I figured that it would -be easy to fit on the character limit, but I missed three -things, the enormous X11 names, the unportable keycodes and my -2 KB of artwork. +be easy to fit on the character limit, but I missed three things: the enormous +X11 names, the non-portable key codes and my 2 KB of artwork. -Very hard coding did the first thing, in fact I worked out -twenty-nine different versions, at one step I had four -parallel versions with different characteristics removed -(mountains, horizon line, score/status bars and explosions), -I've managed to fit it all together!. +Very hard coding did the first thing. In fact I worked out twenty-nine different +versions and at one step I had four parallel versions with different +characteristics removed (mountains, horizon lines, score/status bars and +explosions) but I've managed to fit it all together! -The second thing was solved using the makefile, it is under -160 bytes and you get adjustable keyboard. The greatest -mistery on the earth is why X11 handles unportable keycodes to +The second thing was solved using the Makefile: it is under +160 bytes and you get adjustable controls. The greatest +mystery on the Earth is why X11 gives non-portable key codes to the user. -And finally, the third "Thing" was growing and growing, and -growing, eating bytes for lunch... after endless rounds of -crunching I obtained three-hundred seventy-eight bytes of -artwork and guess what?, it doesn't fitted. +And finally, the third "Thing" was growing and growing, and +growing, eating bytes for lunch... after endless rounds of +crunching I obtained three-hundred seventy-eight bytes of +artwork and guess what? It doesn't fit. -So I had to integrate a decompressor, based on the space, -tabulators and other non-counted characters. +So I had to integrate a decompressor based on the space, tabulators and other +non-counted characters. -The final program is composed of eight microfunctions, one is -the core and does most of the hard work, other functions help -doing the X11 things, explosion effects, 3-D calculations and -viewing. +The final program is composed of eight micro-functions: one is the core and does +most of the hard work and the other functions help do the X11 things, explosion +effects, 3D calculations and viewing. -* K() - 3-D transformation -* s() - Rendering -* b() - Line color selection -* G() - Explosion animation -* g() - Moves 3-D object backward and forward -* F() - Collision detection -* T() - Core (also known as main loop :D) -* main() - Initialization and uncruncher, what a common name!, - C programs should start in the cool() function :). +* `K()` - 3D transformation +* `s()` - Rendering +* `b()` - Line color selection +* `G()` - Explosion animation +* `g()` - Moves 3D object backward and forward +* `F()` - Collision detection +* `T()` - Core (also known as main loop :D) +* `main()` - Initialization and 'uncruncher', what a common name!; + C programs should start in the cool() function :). -The source code was formatted as an cube using a specially -written program, the reality is that the program is smaller and -obfuscated of what is needed so the reformatting doesn't -exceeded the character limits, the crunched vectors were -generated by another special program and the tank that -surrounds this text was generated by yet another program. +The source code was formatted as a cube using a specially written program. This +program is smaller and obfuscated what is needed so the reformatting doesn't +exceeded the character limits. The crunched vectors were generated by another +special program and the tank that surrounds this text was generated by yet +another program. *Have fun!* diff --git a/2011/vik/.gitignore b/2011/vik/.gitignore index c28f954b2..2b2875d14 100644 --- a/2011/vik/.gitignore +++ b/2011/vik/.gitignore @@ -1 +1,3 @@ vik +audio_file.raw +vik.alt diff --git a/2011/vik/Makefile b/2011/vik/Makefile index 375081a9b..4fe7bbd4d 100644 --- a/2011/vik/Makefile +++ b/2011/vik/Makefile @@ -112,8 +112,8 @@ OBJ= ${PROG}.o DATA= mad_world.mod randowan.mod raw2wav TARGET= ${PROG} # -ALT_OBJ= -ALT_TARGET= +ALT_OBJ= ${PROG}.alt.o +ALT_TARGET= ${PROG}.alt ################# diff --git a/2011/vik/README.md b/2011/vik/README.md index 0c683eac0..8dc72df8d 100644 --- a/2011/vik/README.md +++ b/2011/vik/README.md @@ -1,10 +1,8 @@ # Most sound - Daniel Vik - 802 Durshire Way - Sunnyvale, Ca 94087 - - +Daniel Vik + + ## To build: @@ -18,6 +16,15 @@ make ./vik file.mod > audio_file.raw ``` +An alternate version for Windows is available. See the Alternate code section +below. + +### INABIAF - it's not a bug it's a feature! :-) + +The author stated that the program will crash if no argument is passed tot he +program though we note that your computer might also [halt and catch +fire](https://en.wikipedia.org/wiki/Halt_and_Catch_Fire_(computing)) :-) + ## Try: ```sh @@ -31,22 +38,31 @@ Alternatively, you can use: ./vik file.mod > file.raw; ./raw2wav file.raw > file.wav ``` -It is possible to download a number of Mod files from [The Mod Archive](http://modarchive.org). +It is possible to download a number of Mod files from [The Mod +Archive](http://modarchive.org). + +### Alternate code: + +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson), though he feels +slightly sick :-), added a version for Windows based on the author's comments +(along with looking up the function for the right header file). To build try the +alt rule of the Makefile. Assuming that `make` is similar enough try: + +```sh +make alt + +``` + +Use `vik.alt` as you would `vik` above. ## Judges' remarks: -The randowan.mod and mad_world.mod files were created by -[Henrik Bertilsson](http://www.translucentboy.com) and -are included with his permission. - -### Selected Judges Remarks: - This entry converts .MOD audio files to a playable stream in a most pleasing manner if you don't like tremolo or vibrato. Also it abuses the C compiler and/or assembler with a partially -initialized 32 MByte array. Can you tell what is that partial -initilzation for? +initialized 32MB array. Can you tell what that partial +initialization for? Does it take your system a long time to compile? You may want to do try: @@ -55,100 +71,115 @@ cc -S vik.c ``` and to examine the resulting assembly file vik.s. On some platforms -the assembly file is about 128 MBytes in size! +the assembly file is about 128MB in size! + +NOTE: The [randowan.mod](randowan.mod) and [mad_world.mod](mad_world.mod) files were +created by [Henrik Bertilsson](http://www.translucentboy.com) and are included +with his permission. ## Author's remarks: ### Introduction -In 1987, Karsten Obarski changed the way music was handled in games and -demos with the introducton of the MOD file format on Commodore Amiga. +In 1987, [Karsten +Obarski](http://www.vgmpf.com/Wiki/index.php?title=Karsten_Obarski) [changed the +way](https://en.wikipedia.org/wiki/Ultimate_Soundtracker) music was handled in games and +demos with the introduction of the MOD file format on [Commodore +Amiga](https://en.wikipedia.org/wiki/Amiga) -A MOD file contains a set of samples, a number of patterns indicating -how and when the samples are to be played, a list of what patterns to -play in what order, and a number of effects. +A MOD file contains a set of samples, a number of patterns indicating how and +when the samples are to be played, a list of what patterns to play in what +order, and a number of effects. ### Features -This program converts MOD files created with the standard trackers for -Amiga, e.g. Pro Tracker, Noise Tracker and Sound Tracker to raw 16 bit -44.1kHz stereo audio. The program supports MOD music with 4, 6, and 8 +This program converts MOD files created with the standard trackers for +Amiga, e.g. Pro Tracker, Noise Tracker and Sound Tracker to raw 16 bit +44.1kHz stereo audio. The program supports MOD music with 4, 6, and 8 channels MOD files with up to 31 samples. -The MOD format includes many effects for each audio channel and this +The MOD format includes many effects for each audio channel and this program supports most of them, including: - * Arpeggio - * Slide and fine slide up/down/to note - * Set sample offset - * Volume slide - * Pattern break - * Filter on/off - * Set volume - * Cut sample - * Delay sample - * Delay pattern - * Set speed +* Arpeggio +* Slide and fine slide up/down/to note +* Set sample offset +* Volume slide +* Pattern break +* Filter on/off +* Set volume +* Cut sample +* Delay sample +* Delay pattern +* Set speed -Due to size constraints tremolo and vibrato is not supported. Also, to +Due to size constraints tremolo and vibrato is not supported. Also, to avoid infinite long songs, the position jump feature is ignored. ### Songs -With his permission, the package incldues two songs composed by Henrik +With his permission, the package includes two songs composed by Henrik Bertilsson, also known as Deelite: - 1. Mad World - 2. Randowan +1. Mad World +2. Randowan ### Build -Compiling for *nix systems (including cygwin) is straight forward: +Compiling for Unix systems (including cygwin) is straight forward: - $ gcc -o vik vik.c +```sh +gcc -o vik vik.c +``` ### Usage ### Convert MOD file to raw 44.1kHz stereo audio file - $ ./vik mad_world.mod > audio_file.raw +```sh +./vik mad_world.mod > audio_file.raw +``` ### Listen to the MOD file (streaming to mplayer) - $ ./vik randowan.mod | mplayer -demuxer rawaudio - +```sh +./vik randowan.mod | mplayer -demuxer rawaudio - +``` -(Don't forget the last '-' as it makes mplayer read from stdin.) +(Don't forget the last `-` as it makes mplayer read from stdin.) ### Obfuscation -The IOCCC rules did not put a limit on the entropy of the source code, -and it appears that the general entropy rules doesn't apply. An estimate -is that the code density entropy of this entry is ~1.2 which means that +The IOCCC rules did not put a limit on the entropy of the source code, +and it appears that the general entropy rules don't apply. An estimate +is that the code density entropy of this entry is `~1.2` which means that there are around 2500 characters of code carrying information, yet there -are only 2037 IOCCC characters of actual code. Most of the additional -characters are encoded with non-counting characters in the frequency -table. But there are also ~50 or so white space characters spread out +are only 2037 IOCCC characters of actual code. Most of the additional +characters are encoded with non-counting characters in the frequency +table. But there are also `~50` or so white space characters spread out through the source code that carry information. -The use of macros certainly adds to the obfuscation but the reason for +The use of macros certainly adds to the obfuscation but the reason for using them is mainly to fit as many features as possible within the size limits. So please excuse the use of them. -Once the preprocessor is run, the code gets more interesting. The MOD -player is basically a register based state machine and all the magic is -hidden in a fog of short statements. Many of the register updates are -conditional and the program uses the ? operator (sigh) mainly to save -space, but also to leverage the comma operator and precedence more -efficiently. +Once the preprocessor is run, the code gets more interesting. The MOD player is +basically a register based [state +machine](https://en.wikipedia.org/wiki/Finite-state_machine) and all the +[magic][] is hidden in a fog of short statements. Many of the register updates +are conditional and the program uses the `?:` operator (sigh) mainly to save +space, but also to leverage the comma operator and precedence more efficiently. + +[magic]: https://en.wikipedia.org/wiki/Magic_(programming)#Variants ### Portability -The progam is portable to most platforms. The only system dependency is +The program is portable to most platforms. The only system dependency is that the program relies on writing binary data to stdout. -Microsoft compilers adds a carriges return to newlines, and to compile -the program with this platform, the following line can be added after +Microsoft compilers adds a carriage return to newlines, and to compile +the program with this platform, the following line can be added after the main declaration in order for the program to run correctly: ```c @@ -157,7 +188,7 @@ _setmode(_fileno(stdout), 0x8000); ### Limitations -The program only runs when a valid MOD file is passed as argument. If +The program only runs when a valid MOD file is passed as argument. If no argument is passed, the program crashes. ## Copyright and CC BY-SA 4.0 License: diff --git a/2011/vik/vik.alt.c b/2011/vik/vik.alt.c new file mode 100644 index 000000000..82b71aa9e --- /dev/null +++ b/2011/vik/vik.alt.c @@ -0,0 +1,93 @@ +#include +#include +#include + +char E[1<<25]=" ; } } { { } { { ; ; { } } { { ; { { { { { } ; } { { ; { { { ; { } ; ; ; { ; ; ; } } ; } { { ; } } ; } } ; ; } { ; } } { } } } } } ; { { } } } ; } } } { } ; ; ; { } ; { { { ; { ; } } { { { } { { ; ; { { } } { { ; { { { { { } ; } { { ; { { { ; { } ; ; ; ; ; } } ; } { { ; } } ; } ; ; } { ; } } } } } } } ; { { } ; ; } ; { } ; ; ; { } ; { { ; { ; } } { { { } { ; ; { { } } { { { { { { { { ; { ; { { ; { { ; ; { } ; ", +*a[40],*q=E+20,*T=E+1080; +int i=1,j,k,l,u,w,I,J,K,h,H,G,R=4,U,e[999],*p=e+5,*r,*s,*v,b[999],L[1<<16], +F=882,n[99]; +FILE*f; + +#define Y(a,b) (a)<(b)?(a):(b) +#define Z(a,b) (a)>(b)?(a):(b) +#define X(x,a,b)Z(a,Y(b,x)) +#define O [s] +#define N [v] +#define M [r] +#define C ++ +#define m :0 +#define g m, +#define d u== +#define z(o) 32 O?n[X(32 O+o+(35 O-24)/256,0,59)]m +#define y(o) 32 O?8 O=z(o)m +#define x (p=e+5*34 O,2 M-3 && 2 M-5?y(0),l=p[4],a[i]=a[8+34 O],3 N=l>1?\ + 2*(p[3]+l):2*p[0],4 N=l>1?2*l:1,0 N=Y(2 M-9?0:9 O<<8,3 N-1) m) +#define W(t,i) (u=t[i]>>4,w=t[i]&15), +#define Q(e) ((1 N+=13200)>=5 N?1 N-=5 N, C 0 N>=3 N?0 N-=4 N m g e*6 N*q[0\ + N]/34)+ +#define D(b,i) T[i]==*#b&&T[i+2]==#b[1] +#define A ((unsigned char*)q) +#define V *p C= +#define S(a) V(A[a]<<8)|A[a+1], +#define P 2 M== +#define B ,putchar +#define o for( + +int main(int t,char**c) +{ + _setmode(_fileno(stdout), 0x8000); + o; w=E[u]; C u)n[u/10]+=(w-59?w-125?w-32?1 m:2:3)<15?132:128; + k<128; + k C) G=X(G,T[k]+1,128); + o p=L; j Cl?8 O=Z(8 O-3 O,l):8 O>4)-13))?32 O=1 M,x g + 0 O=P 12?X(3 M,0,64) m O , + P 15?(l=3 M)?l<33?t=l:(F=110250/l) m g + P 14? + W(r,3) + j?(16+u) O=j g + 8 O=d 1?Z(113,8 O-17 O):d 2?Y(856,8 O+18 O):8 O, + d 5?35 O=(j&7)-2*(j&8) g + d 9?39 O=25 O&&!1 M?x,0 m g + 0 O=d 10?Y(0 O+26 O,64):d 11?Z(0 O-27 O,0):0 O, + d 14?h=30 O m m), + 6 N =X(0 O,0,64), + 5 N =999*8 O, + i C); + o C I>=t+t*h?I=h=0,C J>=64?J=0,U|=C K>=H m g j=F; j--; 0 + B(u)B(u>>8)B(w)B(w>>8)) + o i=u=w=0; i - +Matt Zucker + + ## To build: @@ -19,12 +19,21 @@ make ## Try: ```sh -./zucker "Hello!!!" > hello.ppm +./zucker "Hello\!\!\!" > hello.ppm ./zucker faster\! -preview > image2.ppm ``` Display the PPM image with your favorite image viewer. +The author gave options for macOS but we note that you can just do: + +```sh +open image.ppm +``` + +which will open `Preview.app` which will let you look at the image no problem. +No need to install additional software. + ## Judges' remarks: The rendered image is centered and is output as a 600 by 220 pixel PPM. @@ -36,7 +45,7 @@ This entry uses no local variables. None! At! All! ### An image generator -### What it does: +#### What it does: This program makes pretty pictures. To see the default output, try running @@ -62,7 +71,7 @@ program as follows: ./zucker "your text" > image.ppm ``` -To mitigate long runtimes, the program can be invoked in a "preview" +To mitigate long runtime, the program can be invoked in a "preview" mode by appending `-preview` to the command line arguments, like so: ```sh @@ -73,7 +82,7 @@ If your platform distinguishes between binary and text streams, you may need to insert some code to reopen standard output in binary mode at the start of `main`. An ASCII platform is assumed. -### Pedagogical value: +#### Pedagogical value: This program is quite suitable for the inexperienced programmer, due to a number of considerations: @@ -101,7 +110,7 @@ to a number of considerations: reflection ray at an object's surface, given the incoming direction and surface normal. -### Further details (contains spoilers): +#### Further details (contains spoilers): The program is not quite a traditional ray tracer, but a "sphere tracer" which uses distance fields to encode proximity to objects in @@ -135,14 +144,14 @@ it is impossible to modify either the image width or height without changing the source in at least three different places, including inside the large string literal. -Some of the functions are simple vector algebra operations such as +Some of the functions are simple vector algebraic operations such as vector construction, dot product, and normalization. However, it was found to be much more compact to define a single operation for multiply-and-add rather than to have separate functions for addition, subtraction, and scaling. Again, compactness led to obfuscation. This program heavily abuses `for` loops. The comma operator is used to -get as much milage as possible out of statements inside of loop +get as much mileage as possible out of statements inside of loop declarations. Between `for` loops, the comma operator, and the ternary operator, it was possible to avoid `if` and `while` altogether. @@ -155,7 +164,7 @@ performed just about everywhere. Fascinatingly, this doesn't seem to affect performance too badly. Sometimes when an explicit cast (i.e. from float to int) is needed, the program instead simply assigns to a free variable of the desired type instead. Both the `array[index]` -and `index[array]` notations are used interchangably throughout the +and `index[array]` notations are used interchangeably throughout the program. Two other programs were written to support development of this diff --git a/2012/blakely/.gitignore b/2012/blakely/.gitignore index e9ebfc303..4931758f0 100644 --- a/2012/blakely/.gitignore +++ b/2012/blakely/.gitignore @@ -3,4 +3,6 @@ output.gif paraboloid.gif empty.gif flat.gif - +pic.gif +ripple.gif +saddle.gif diff --git a/2012/blakely/README.md b/2012/blakely/README.md index 88a4ad045..f4c75cd49 100644 --- a/2012/blakely/README.md +++ b/2012/blakely/README.md @@ -1,8 +1,8 @@ # Most GIFted expressions - Philip Blakely - Cambridge, UK - +Philip Blakely +UK + ## To build: @@ -28,7 +28,11 @@ time ./blakely 0 250 > flat.gif ## Judges' remarks: -Several IOCCC themes (RPN calculator, animated GIF generator, ray tracing) in one package! Very impressive! +Several IOCCC themes ([RPN +calculator](https://en.wikipedia.org/wiki/Reverse_Polish_notation), animated +[GIF](https://en.wikipedia.org/wiki/GIF) generator, [ray +tracing](https://en.wikipedia.org/wiki/Ray_tracing_(graphics))) in one package! +Very impressive! The checkerboard pattern in the output can be broken. Could you figure out how? @@ -38,9 +42,13 @@ Larger GIF files confuse some image viewers. ### Remarks -This program renders a generic RPN expression in ray-traced animated GIF form. -The expression in spatial variables x and y is specified on the command-line with the required resolution, -and an animated GIF showing a fly-around of the resulting surface is output to stdout. +This program renders a generic +[RPN](https://en.wikipedia.org/wiki/Reverse_Polish_notation) expression in +[ray-traced](https://en.wikipedia.org/wiki/Ray_tracing_(graphics)) animated +[GIF](https://en.wikipedia.org/wiki/GIF) form. The expression in spatial +variables `x` and `y` is specified on the command-line with the required +resolution, and an animated GIF showing a fly-around of the resulting surface is +output to stdout. ### Usage @@ -50,32 +58,46 @@ The program should be run as: ./blakely xy* 32 > pic.gif ``` -where the first parameter is a RPN expression, and the second is the width of the required GIF, up to a maximum of 250. +where the first parameter is a +[RPN](https://en.wikipedia.org/wiki/Reverse_Polish_notation) expression, and the +second is the width of the required [GIF](https://en.wikipedia.org/wiki/GIF), up +to a maximum of 250. -The expressions are written in Reverse Polish Notation with the following characters recognised: +The expressions are written in [Reverse Polish +Notation](https://en.wikipedia.org/wiki/Reverse_Polish_notation) with the +following characters recognised: -* +,-,\*,/ - usual arithmetic operations -* ^ - Exponentiation - valid for constant exponent only -* s - sin -* c - cos -* 0-9 - single digit integers -* d - duplicate number on stack -* t - transpose top two elements on stack -* x - x coordinate value -* y - y coordinate value +``` ++, -, *, / - usual arithmetic operations +^ - Exponentiation; valid for constant exponent only +s - sin +c - cos +0-9 - single digit integers +d - duplicate number on stack +t - transpose top two elements on stack +x - x coordinate value +y - y coordinate value +``` -NB all arithmetic is done in double precision, so 23/ is two-thirds, rather than 0 +NB all arithmetic is done in double precision, so `23/` is two-thirds, rather +than 0. -The surface plotted corresponds to -1 <= x,y <= 1 and for best results, the generated z value should lie between -1 and 1. +The surface plotted corresponds to `-1 <= x,y <= 1` and for best results, the +generated `z` value should lie between `-1` and `1`. -If there is a division by zero, square-root of a negative number, or similar operation, then the results are undefined. +If there is a division by zero, square-root of a negative number, or similar +operation, then the results are undefined. ### Examples -For test-runs, use a resolution of 32. For simple expressions, the GIF generation should take only -a few seconds with a modern processor and full optimization. Run-time scales as O(N^3) with resolution N, -and more complex expressions take longer to compute. For example, increasing the resolution of ripple.gif -to 250 took ~35 minutes to render on an i7 processor. +For test-runs, use a resolution of 32. For simple expressions, the +[GIF](https://en.wikipedia.org/wiki/GIF) generation should take only +a few seconds with a modern processor and full optimization. Runtime scales as +[O(N^3)](https://en.wikipedia.org/wiki/Big_O_notation) with resolution `N`, +and more complex expressions take longer to compute. For example, increasing the +resolution of `ripple.gif` +to 250 took ~35 minutes to render on an [i7 +processor](https://en.wikipedia.org/wiki/Intel_Core#Core_i7). ```sh ./blakely xy* 32 > saddle.gif @@ -86,33 +108,41 @@ to 250 took ~35 minutes to render on an i7 processor. ### Algorithm A generic root-finding algorithm to find the point of intersection between a ray -and the surface is done using a simple forward search from the eye. -In order to make the rendering realistic, both the value of the expression, and its derivative with respect to x and y must be tracked. -This is done using an obvious stack-based approach. +and the surface is done using a simple forward search from the eye. In order to +make the rendering realistic, both the value of the expression, and its +derivative with respect to `x` and `y` must be tracked. This is done using an +obvious stack-based approach. ### Obfuscations -Much of the obfuscation is achieved through the use of single-letter variables and #defines. -The characters output for the GIF format are generated in myriad and wonderful ways, making use -of XOR, return values from putchar, and odd expressions. -The layout is in the form of X Y Z. +Much of the obfuscation is achieved through the use of single-letter variables +and `#define`s. The characters output for the [GIF +format](https://en.wikipedia.org/wiki/GIF#File_format) are generated in myriad +and wonderful ways, making use of +[XOR](https://en.wikipedia.org/wiki/Exclusive_or), return values from +`putchar()`, and odd expressions. The layout is in the form of `X Y Z`. ### Limitations -ASCII is assumed since many bytes for the GIF output are generated from characters given in the source code. -On compilation a few warnings about parentheses come up when using gcc 4.6.3, and one about no return value from main() (who uses exit codes anyway?), -but clang 3.1 emits no warnings. +ASCII is assumed since many bytes for the +[GIF](https://en.wikipedia.org/wiki/GIF) output are generated from characters +given in the source code. On compilation a few warnings about parentheses come +up when using gcc 4.6.3, and one about no return value from `main()` (who uses +exit codes anyway?), but clang 3.1 emits no warnings. ### Questions -* Apart from their appearance when computing the RPN expression, sin and cos are not used. +* Apart from their appearance when computing the [RPN +expression](https://en.wikipedia.org/wiki/Reverse_Polish_notation), [sin and +cos](https://en.wikipedia.org/wiki/Sine_and_cosine) are not used. How do we then get the correct angles for rotation? * Exactly how many times will the animation repeat? * Why is there an upper limit of 250x250 for the resolution? -* What is the point of b[0]? -* Where are the words NETSCAPE and GIF hidden in the source? +* What is the point of `b[0]`? +* Where are the words `NETSCAPE` and `GIF` hidden in the source? -(Note that the author may or may not be able to answer all of the above questions.) +(Note that the author may or may not be able to answer all of the above +questions.) ## Copyright and CC BY-SA 4.0 License: diff --git a/2012/deckmyn/.gitignore b/2012/deckmyn/.gitignore index 45ebaf614..2e28a65dc 100644 --- a/2012/deckmyn/.gitignore +++ b/2012/deckmyn/.gitignore @@ -4,3 +4,4 @@ greensleeves.pbm sheetmusic.pbm sheetmusic.pbm sheetmusic.pbm +output.pbm diff --git a/2012/deckmyn/MANUAL b/2012/deckmyn/MANUAL deleted file mode 100644 index bc729e1bf..000000000 --- a/2012/deckmyn/MANUAL +++ /dev/null @@ -1,58 +0,0 @@ -USER MANUAL -=========== - -Calling the program -------------------- - -./prog "`cat prog.c`" "`cat musicfile`" > output.pbm -display output.pbm - -This minimalistic music notator expects two command line arguments. The first is the font description embedded in the source code. Notice that you don't pass the file name, but the actual content as one long character string! If you want to define your personal music font, you can of course do so. The file layout must be exactly the same as prog.c though, only the locations of space (" ") may differ. - -The second argument is the actual music. Again it is one long string, not a file name. But it is possible to save your music in a file, of course. - -Output should be redirected to a file. Afterwards, this file can be visualised with various viewers. - - -Music input ------------ - -Every element in the music is given by a string of *exactly* 3 characters. Any violation of this will result in the rest of the music being interpreted in some randomly wrong way. Notice that in a file, the newline is also a character! Therefore, when preparing music in a file, care shold be taken that the last musical element of a line is only 2 characters! - -1. Basic notes: -A single note is input by a letter [A-Ga-g] followed by a duration [1,2,4,8] and possibly a dot [.]. The notes cover 2 octaves, from C (lowest) to b (highest). The possible durations are 1 (whole note), 2 (half note), 4 (quaver), 8 (semi-quaver). So a dotted quaver A followed by a semi quaver G is input as "A4.G8 " - -2. Rests: -A rest is given by the letter [r] followed by a duration [1,2,4,8]. - -3. Bar lines: -There are three possible barline types: single (": "), double (":: ") and final (":; "). - -4. Accidentals: -Chromatic changes (sharp, flat, natural) are entered separately from the note that folows them! They are a three-character sequence by themselves. The first character is the chromatic change [+-=]. The second is the pitch at which it should be drawn. Thus "+G G4 " will draw a G sharp quaver. Notice that these signs do not necessarily have to be followed by a note. "+f +c +g B2 " is perfectly legal. - -5. Space (formatting): -To manually change the spacing of the music, you can add space between different musical elements. This is given by a [s] followed by the amount of space."s3 " is the space taken by one note. This length is given in 1 character. However, to get a value larger than 9, you can just continue along the ASCII table. So "sz " gives you quite a lot of space on a staff. "s0 " is not only meaningless, it can cause nasty results. - -6. New staff: -A token "x " signifies to start a new staff of music. A music staff may never be empty! Even if you just put some blank space ("s1 "), you should always have an entry for every staff. "x x " may give nasty results. - -All staves in the output are extended to the length of the longest staff. To have nicely formatted music, though, you will probably have to add spaces manually. - -7. Time signatures: -A time signature is given by [m][234][234]. For example, "m24" will give you a two fourth signature. Notice that there are only three available numbers. Especially "6" and "8" are dearly missed. - -8. Clef: -The clef (G or F) can only be changed at the beginning of the music input. If the music starts with "KF ", the music will be written in a bass cleff. "K" followed by any other letter will just default to a standard G clef. - -Examples --------- - -Blank music paper (with G cleff): -./prog "`cat prog.c`" "sz sa x s1 x s1 x s1 x s1 x s1 "> blank.pbm -with an F cleff: -./prog "`cat prog.c`" "KF sz sa x s1 x s1 x s1 x s1 x s1 "> blank.pbm - -Notice how only the first staff (or any staff) needs to have the full length. - -Some files with well-known melodies are included as examples. diff --git a/2012/deckmyn/Makefile b/2012/deckmyn/Makefile index 6ff9e42c6..ecea14aec 100644 --- a/2012/deckmyn/Makefile +++ b/2012/deckmyn/Makefile @@ -110,7 +110,7 @@ ENTRY= deckmyn PROG= ${ENTRY} # OBJ= ${PROG}.o -DATA= MANUAL example_beethoven example_greensleeves +DATA= deckmyn.md example_beethoven example_greensleeves TARGET= ${PROG} # ALT_OBJ= diff --git a/2012/deckmyn/README.md b/2012/deckmyn/README.md index 84d8237f1..75243815c 100644 --- a/2012/deckmyn/README.md +++ b/2012/deckmyn/README.md @@ -1,7 +1,7 @@ # Most notable and best tool - Alex Deckmyn - +Alex Deckmyn + ## To build: @@ -29,16 +29,21 @@ The C of this entry is definitely sharp. The program cleverly uses its own source at runtime to define the notes, time signature and accidental bitmaps. In addition to sheet music, this program is also able, given the right input, -to generate an image of a 10-pin DIP chip (a sound processor?). +to generate an image of a 10-pin [DIP +chip](https://en.wikipedia.org/wiki/Dual_in-line_package) (a sound processor?). -Ironically, the way this entry is called from the command line is an abuse of C Shell. -Please use Bourne-family shells to run this entry. +Ironically, the way this entry is called from the command line is an abuse of [C +Shell](https://en.wikipedia.org/wiki/C_shell). +Please use [Bourne-family shells](https://en.wikipedia.org/wiki/Bourne_shell) to +run this entry. ## Author's remarks: ### Example use -You need the source code and example input (either one of the example files, or manual input as below) ready. And a program capable of showing .pbm bitmap format. +You need the source code and example input (either one of the example files, or +manual input as below) ready and a program capable of showing [.pbm bitmap +format](https://en.wikipedia.org/wiki/Netpbm). ```sh ./deckmyn "`cat deckmyn.c`" "`cat example_greensleeves`" > greensleeves.pbm @@ -50,48 +55,88 @@ open greensleeves.pbm open short_bass.pbm ``` -## Judges' remarks: - ### Description Every major C competition should have an entry capable of producing C major. -This is a music notation program. It produces bitmaps (.pbm) of music based on ASCII input. A full manual is added as a separate file. Some musical examples are also included. +This is a music notation program. It produces +[bitmaps](https://en.wikipedia.org/wiki/Netpbm) (`.pbm`) of music based on ASCII +input. A full manual is added as a [separate file](deckmyn.md). Some musical +examples are also included. -The program is capable of printing notes, rests, (double) bar lines and accidentals on a single melodic line (multiple staves). No chords, polyphony etc. +The program is capable of printing notes, rests, (double) bar lines and +accidentals on a single melodic line (multiple staves). No chords, polyphony +etc. -The program expects *two command line arguments*. The first is a (very long) string that contains the complete music font. Note that it should *not* be given as a file name! The default music font is encoded in the (whitespace of the) source code deckmyn.c itself. Therefore, the first argument should be "`cat deckmyn.c`". +The program expects *two command line arguments*. The first is a (very long) +string that contains the complete music font. Note that it should *not* be given +as a file name! The default music font is encoded in the (whitespace of the) +source code [deckmyn.c](deckmyn.c) itself. Therefore, the first argument should +be `"cat deckmyn.c"`. -The second command line argument is the music itself. This is, again, a string, not a file name. All music signs are entered as tokens of exactly 3 characters. The code is very sensitive to bad spacing! So for instance, if you use a file to write the music (e.g. example\_greensleeves), you should keep in mind that newline is also a character! +The second command line argument is the music itself. This is, again, a string, +not a file name. All music signs are entered as tokens of exactly 3 characters. +The code is very sensitive to bad spacing! So for instance, if you use a file to +write the music (e.g. [example\_greensleeves](example_greensleeves)), you should +keep in mind that newline is also a character! ### Internals -To minimise the memory footprint, this program has *no variable declarations at all*, except for the arguments to main(). The only available memory space is from the command line arguments and count (argv and argc). Parts of argv are cast as integer when values under 0 or beyond 127 are expected. +To minimise the memory footprint, this program has *no variable declarations at +all*, except for the arguments to `main()`. The only available memory space is +from the command line arguments and count (`argv` and `argc`). Parts of `argv` +are cast as integer when values under 0 or beyond 127 are expected. -The "music font" is defined by the source code itself. The first few lines are not part of the font definition, as this memory space will modified by the program. (So as required by the rules, it is only a (memory) copy of the source code that is modified.) +The "music font" is defined by the source code itself. The first few lines are +not part of the font definition, as this memory space will modified by the +program. (So as required by the rules, it is only a (memory) copy of the source +code that is modified.) -As there is no memory available, output is directly to stdout, byte by byte, from the top left to the bottom right pixel. +As there is no memory available, output is directly to stdout, byte by byte, +from the top left to the bottom right pixel. ### LIMITATIONS -The memory locations of argv are used for various purposes. Therefore, the program name (default "deckmyn") must be *at least 4 characters long*, including possibly the path. This, along with the ending '\0', gives minimum 5 bytes of useful memory space. Otherwise, the program may attempt to write outside the string. +The memory locations of `argv` are used for various purposes. Therefore, the +program name (default `deckmyn`) must be *at least 4 characters long*, including +possibly the path. This, along with the ending `'\0'`, gives minimum 5 bytes of +useful memory space. Otherwise, the program may attempt to write outside the +string. -The code is quite sensitive. Errors in the input can lead to strange results. The code does not read beyond the end of the music input, but that is about the only error checking available. Any input that is not according to the rules in the MANUAL, may cause errors. +The code is quite sensitive. Errors in the input can lead to strange results. +The code does not read beyond the end of the music input, but that is about the +only error checking available. Any input that is not according to the rules in +the [manual](deckmyn.md), may cause errors. -The program has no special hardware limitations or requirements, other than 8bit char (signed or unsigned) and two's complement negatives. +The program has no special hardware limitations or requirements, other than 8bit +char (signed or unsigned) and two's complement negatives. -The limitations of using char as counters for e.g. the number of music staves are minor. 127 staves to a page is rather a lot. +The limitations of using char as counters for e.g. the number of music staves +are minor. 127 staves to a page is rather a lot. ### Obfuscations -The code has no declared variables other than the command line variables. Not even pointers (we all know how messy code can get with too many pointers!). As more than one variable needs values beyond 127, parts of the command line memory are cast as integer using a macro. +The code has no declared variables other than the command line variables. Not +even pointers (we all know how messy code can get with too many pointers!). As +more than one variable needs values beyond 127, parts of the command line memory +are cast as integer using a macro. -- The formatting of the code is in fact necessary, as this is the definition of the music font. It is therefore not an obfuscation. -- The use of only argv/argc as memory locations is a matter of reducing the memory footprint. Again, it is not an obfuscation. -- Calling the only remaining variables, and the two defined macros, c and C, is merely a matter of conforming to the standard WYSIWYG paradigm common in commercial notation programs (What You C is What You Get). So once again it is not an obfuscation. Anyway, it's a C coding contest, right? -- Randomly using the numerical (ASCII) value for characters is compensated for by replacing some numbers by a character representation. On average, therefore, it is not an obfuscation. -- Randomly changing the way the elements of argv are addressed is a matter of maintaining a diversified code base. It is therefore not... Oh allright. -- The actual output of the music is done by one print command including a 800+ character nested conditional expression. -- printf is also used for its return value. +- The formatting of the code is in fact necessary, as this is the definition of +the music font. It is therefore not an obfuscation. +- The use of only `argv`/`argc` as memory locations is a matter of reducing the +memory footprint. Again, it is not an obfuscation. +- Calling the only remaining variables, and the two defined macros, `c` and `C`, +is merely a matter of conforming to the standard +[WYSIWYG](https://en.wikipedia.org/wiki/WYSIWYG) paradigm common in commercial +notation programs ('What You `C` is What You Get). So once again it is not an +obfuscation. Anyway, it's a C coding contest, right? +- Randomly using the numerical (ASCII) value for characters is compensated for +by replacing some numbers by a character representation. On average, therefore, +it is not an obfuscation. +- Randomly changing the way the elements of `argv` are addressed is a matter of +maintaining a diversified code base. It is therefore not... Oh all right. +- The actual output of the music is done by one print command including a 800+ +character nested conditional expression. +- `printf()` is also used for its return value. ## Copyright and CC BY-SA 4.0 License: diff --git a/2012/deckmyn/deckmyn.md b/2012/deckmyn/deckmyn.md new file mode 100644 index 000000000..825818567 --- /dev/null +++ b/2012/deckmyn/deckmyn.md @@ -0,0 +1,98 @@ +# USER MANUAL + +## Calling the program + +```sh +./deckmyn "`cat deckmyn.c`" "`cat musicfile`" > output.pbm +``` + +Then display `output.pbm`. + +This minimalistic music notator expects two command line arguments. The first is +the font description embedded in the source code. Notice that you don't pass the +file name, but the actual content as one long character string! If you want to +define your personal music font, you can of course do so. The file layout must +be exactly the same as [deckmyn.c](deckmyn.c) though, only the locations of +space (`" "`) may differ. + +The second argument is the actual music. Again it is one long string, not a file +name. But it is possible to save your music in a file, of course. + +Output should be redirected to a file. Afterwards, this file can be visualised +with various viewers. + + +## Music input + +Every element in the music is given by a string of *exactly* 3 characters. Any +violation of this will result in the rest of the music being interpreted in some +randomly wrong way. Notice that in a file, the newline is also a character! +Therefore, when preparing music in a file, care should be taken that the last +musical element of a line is only 2 characters! + +1. Basic notes: + A single note is input by a letter `[A-Ga-g]` followed by a duration + [1,2,4,8] and possibly a dot [`.`]. The notes cover 2 octaves, from `C` + (lowest) to `b` (highest). The possible durations are 1 (whole note), 2 + (half note), 4 (quaver), 8 (semi-quaver). So a dotted quaver `A` followed by + a semi quaver `G` is input as `"A4.G8 "`. + +2. Rests: + A rest is given by the letter [`r`] followed by a duration [1,2,4,8]. + +3. Bar lines: + There are three possible bar line types: single (`": "`), double (`":: "`) + and final (`":; "`). + +4. Accidentals: + Chromatic changes (sharp, flat, natural) are entered separately from the + note that follows them! They are a three-character sequence by themselves. + The first character is the chromatic change [`+-=`]. The second is the pitch + at which it should be drawn. Thus `"+G G4 "` will draw a G sharp quaver. + Notice that these signs do not necessarily have to be followed by a note. + `"+f +c +g B2 "` is perfectly legal. + +5. Space (formatting): + To manually change the spacing of the music, you can add space between + different musical elements. This is given by a `[s]` followed by the amount + of space. `"s3 "` is the space taken by one note. This length is given in 1 + character. However, to get a value larger than 9, you can just continue + along the ASCII table. So `"sz "` gives you quite a lot of space on a staff. + `"s0 "` is not only meaningless, it can cause nasty results. + +6. New staff: + A token `"x "` signifies to start a new staff of music. A music staff may + never be empty! Even if you just put some blank space (`"s1 "`), you should + always have an entry for every staff. `"x x "` may give nasty results. + + All staves in the output are extended to the length of the longest staff. To + have nicely formatted music, though, you will probably have to add spaces + manually. + +7. Time signatures: + A time signature is given by `[m][234][234]`. For example, `"m24"` will give + you a two fourth signature. Notice that there are only three available + numbers. Especially "6" and "8" are dearly missed. + +8. Clef: + The clef (`G` or `F`) can only be changed at the beginning of the music + input. If the music starts with `"KF "`, the music will be written in a bass + clef. `"K"` followed by any other letter will just default to a standard G clef. + +## Examples + +Blank music paper (with G clef): + +```sh +./deckmyn "`cat deckmyn.c`" "sz sa x s1 x s1 x s1 x s1 x s1 "> blank.pbm +``` + +With an F clef: + +``` +./deckmyn "`cat deckmyn.c`" "KF sz sa x s1 x s1 x s1 x s1 x s1 "> blank.pbm +``` + +Notice how only the first staff (or any staff) needs to have the full length. + +Some files with well-known melodies are included as examples. diff --git a/2012/dlowe/README.md b/2012/dlowe/README.md index 2a54220bf..41a0fa8a3 100644 --- a/2012/dlowe/README.md +++ b/2012/dlowe/README.md @@ -38,17 +38,17 @@ Use up and down keys to escape death. The judges lose playing this game. This entry wins! - Q: How did we get past the variadic macro problem on a Mac? -A: Don't use -pedantic-errors in the Makefile. +A: Don't use `-pedantic-errors` in the Makefile. + ## Author's remarks: ### Conway's Game of DEATH -This is a challenging, fast-paced arcade game, based on the famous Game of -Life. +This is a challenging, fast-paced arcade game, based on the famous [Game of +Life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life). ### Story @@ -63,7 +63,7 @@ escape? No. There is no winning. Sadly for Mr.C, this universe goes on forever. Just see how far you can make it! -Press 'q' any time to quit. +Press `q` any time to quit. ### Features diff --git a/2012/endoh1/.gitignore b/2012/endoh1/.gitignore index 4bda9d8f3..bae478e61 100644 --- a/2012/endoh1/.gitignore +++ b/2012/endoh1/.gitignore @@ -1,3 +1,4 @@ endoh1 endoh1.alt endoh1_color +configuration.txt diff --git a/2012/endoh1/README.md b/2012/endoh1/README.md index 767fa03ad..414e623fc 100644 --- a/2012/endoh1/README.md +++ b/2012/endoh1/README.md @@ -1,8 +1,9 @@ # Most complex ASCII fluid - Honorable mention - Yusuke Endoh - - +Yusuke Endoh + + +Mastodon: [@mame@ruby.social](https://ruby.social/@mame) ## To build: @@ -26,6 +27,11 @@ make ./endoh1 < fountain.txt ``` +Also try using `endoh1_color` as you would `endoh1` above. `make` will compile +this by default. + + + ### Alternate code: An alternate version of this entry, `endoh1.alt.c`, is provided. @@ -41,7 +47,7 @@ Use `endoh1.alt` as you would `endoh1` above. ## Judges' remarks: -Let's play Jeopardy! +Let's play [Jeopardy!](https://en.wikipedia.org/wiki/Jeopardy!) * A: An obfuscated program that deals with complex numbers and produces animated ASCII graphics. * Q: What is a Mandelbrot simulator? @@ -58,7 +64,7 @@ One configuration file was inspired by an [XKCD what if? entry](http://whatif.xk ### Synopsis -**DO NOT FORGET "-DG=1 -DP=4 -DV=8"** and make your terminal window larger +**DO NOT FORGET** `-DG=1 -DP=4 -DV=8` and make your terminal window larger than 80 x 25. ```sh @@ -72,6 +78,7 @@ cc endoh1.c -DG=1 -DP=4 -DV=8 -D_BSD_SOURCE -o endoh1 -lm ### What it is +``` ,___. ,. ,. ,. ,___. ,. ,. ,. |/--' || `' || |/--' `' || |\_. |\__. || ,. ,. ,. ,__/| |\__. ,. ,____. ,. ,. || ,_. |/-' ,_. ,__. @@ -98,10 +105,10 @@ cc endoh1.c -DG=1 -DP=4 -DV=8 -D_BSD_SOURCE -o endoh1 -lm `-'`' `-'`-' `-'`-' `-'`' `'`' `'`' `'`' -This program is a fluid simulator using "Smoothed-particle hydrodynamics (SPH)" -method. +``` - +This program is a fluid simulator using [Smoothed-particle hydrodynamics +(SPH)](http://en.wikipedia.org/wiki/Smoothed-particle_hydrodynamics) method. The SPH particles represent the fluid flow. Particles have information about the position, density, and velocity. In every simulation step, they are @@ -116,20 +123,22 @@ The compilation options `-DG=1 -DP=4 -DV=8` represent, respectively, the factor of gravity, pressure, and viscosity. By changing their values, you can see different fluid behavior. -"Marching square"-like algorithm is used to render the particles. - - +[Marching square](http://en.wikipedia.org/wiki/Marching_squares)-like algorithm +is used to render the particles. ### Portability The program requires a C99 compiler; it uses `complex` types and one-line -comments. It also uses `usleep`, which may require `-D_BSD_SOURCE` or somewhat +comments. It also uses `usleep`, which may require `-D_BSD_SOURCE` or so to build with no warning. Under these conditions, it should be portable. -At least, recent compilers with `-std=c99 -Wall -W -Wextra -pedantic` says +At least, recent compilers with `-std=c99 -Wall -W -Wextra -pedantic` say nothing. - gcc -DG=1 -DP=4 -DV=8 -D_BSD_SOURCE -std=c99 -Wall -W -Wextra -pedantic endoh1.c - clang -DG=1 -DP=4 -DV=8 -D_BSD_SOURCE -std=c99 -Wall -W -Wextra -pedantic endoh1.c +```sh +gcc -DG=1 -DP=4 -DV=8 -D_BSD_SOURCE -std=c99 -Wall -W -Wextra -pedantic endoh1.c + +clang -DG=1 -DP=4 -DV=8 -D_BSD_SOURCE -std=c99 -Wall -W -Wextra -pedantic endoh1.c +``` I expect it to work in any Unix-like environment. VTxxx/ANSI sequences are used to clear screen and move cursor to home. @@ -145,11 +154,12 @@ First of all, the source code itself serves as an initial configuration. Preprocessing directives (such as `#include`)'s `#` serve as walls. This program uses `double complex` to represent any 2D vector. But, note that -x-axis and y-axis is swapped (real axis = y-axis, imaginary axis = x-axis). +`x-axis` and `y-axis` is swapped (real axis = y-axis, imaginary axis = x-axis). The purpose of swapping is not only obfuscation, but also short coding: for example, to add gravity to total force, `force += G` suffices, rather than `force += G*I`. -(Incidentally, you can exert horizontal gravity by using, such as, `-DG=I`) + +(Incidentally, you can exert horizontal gravity by using for instance `-DG=I`) Every five entries of `double complex a[]` contain information of one particle: position, wall-flag, density, force, and velocity, in turn. @@ -163,29 +173,29 @@ casting) it to an integer-type variable. ### Notes about Additional Files -"logo.txt" is a source of the logo in this remark file. +[logo.txt](logo.txt) is a source of the logo in this remark file. -"column.txt" is a water column collapse, which is a popular demo of SPH. +[column.txt](column.txt) is a water column collapse, which is a popular demo of SPH. -"pour-out.txt" pours you a cup of tea. +[pour-out.txt](pour-out.txt) pours you a cup of tea. -"tanada.txt" simulates "Terrace farming". ("Tanada" means a "terraced rice -fields" in Japanese.) +[tanada.txt](tanada.txt) simulates "Terrace farming". ("Tanada" means a "[terraced rice +fields](https://en.wikipedia.org/wiki/Terrace_(earthworks))" in Japanese.) -"clock.txt" is a "water" clock created by HAMANO Tsukasa. +[clock.txt](clock.txt) is a "water" clock created by HAMANO Tsukasa. -Other \*.txt files are due to the judges. +Other `*.txt` files are from the judges. -"endoh1\_color.c" is a variant that shows the density by using terminal 256 +[endoh1_color.c](endoh1_color.c) is a variant that shows the density by using terminal 256 colors. -### Acknowledgment +### Acknowledgments I would like to thank my wife @hirekoke for her teaching me the SPH method. The judges ordered suggested creating a color version -after the judgment. +after the contest. The judges and HAMANO Tsukasa (The silver medalist at this IOCCC) kindly provided many configuration files. diff --git a/2012/endoh2/README.md b/2012/endoh2/README.md index 2389513d6..dc6962948 100644 --- a/2012/endoh2/README.md +++ b/2012/endoh2/README.md @@ -1,8 +1,9 @@ # PiE in the sky award - Yusuke Endoh - - +Yusuke Endoh + + +Mastodon: [@mame@ruby.social](https://ruby.social/@mame) ## To build: diff --git a/2012/tromp/README.md b/2012/tromp/README.md index c11d6ad71..f23fb04dd 100644 --- a/2012/tromp/README.md +++ b/2012/tromp/README.md @@ -10,7 +10,7 @@ John Tromp make tromp32 # On a 32-bit machine -## To run +## To run: ./tromp [-b] diff --git a/2013/endoh1/README.md b/2013/endoh1/README.md index 243540e86..d0cec0b39 100644 --- a/2013/endoh1/README.md +++ b/2013/endoh1/README.md @@ -1,8 +1,9 @@ # Most lazy SKIer - Yusuke Endoh - - +Yusuke Endoh + + +Mastodon: [@mame@ruby.social](https://ruby.social/@mame) ## To build: diff --git a/2013/endoh2/README.md b/2013/endoh2/README.md index f2dbb34b5..e2814ceda 100644 --- a/2013/endoh2/README.md +++ b/2013/endoh2/README.md @@ -1,8 +1,9 @@ # Most recyclable - Yusuke Endoh - - +Yusuke Endoh + + +Mastodon: [@mame@ruby.social](https://ruby.social/@mame) ## To build: diff --git a/2013/endoh3/README.md b/2013/endoh3/README.md index e42a5f2ed..6d90f6657 100644 --- a/2013/endoh3/README.md +++ b/2013/endoh3/README.md @@ -1,8 +1,9 @@ # Most tweetable 1-liner - Yusuke Endoh - - +Yusuke Endoh + + +Mastodon: [@mame@ruby.social](https://ruby.social/@mame) ## To build: diff --git a/2013/endoh4/README.md b/2013/endoh4/README.md index 2df7a0fda..6c57e679e 100644 --- a/2013/endoh4/README.md +++ b/2013/endoh4/README.md @@ -1,8 +1,9 @@ # Most solid - Yusuke Endoh - - +Yusuke Endoh + + +Mastodon: [@mame@ruby.social](https://ruby.social/@mame) ## To build: diff --git a/2014/vik/README.md b/2014/vik/README.md index ec46953f6..6d9b9e402 100644 --- a/2014/vik/README.md +++ b/2014/vik/README.md @@ -1,8 +1,10 @@ # Best handling of beeps - Daniel Vik - - +Daniel Vik +US + + + ## To build: diff --git a/2015/endoh1/README.md b/2015/endoh1/README.md index 22599d106..61de91416 100644 --- a/2015/endoh1/README.md +++ b/2015/endoh1/README.md @@ -1,11 +1,11 @@ # Most Diffused Reaction - Yusuke Endoh - - Twitter: @mametter +Yusuke Endoh + +Mastodon: [@mame@ruby.social](https://ruby.social/@mame) - Someone Anonymous - Twitter: @hirekoke +Someone Anonymous +Twitter: @hirekoke ## To build: diff --git a/2015/endoh2/README.md b/2015/endoh2/README.md index 6a2c416c1..32d3c02c8 100644 --- a/2015/endoh2/README.md +++ b/2015/endoh2/README.md @@ -1,8 +1,8 @@ # Most Overlooked Obfuscation - Yusuke Endoh - - Twitter: @mametter +Yusuke Endoh + +Mastodon: [@mame@ruby.social](https://ruby.social/@mame) ## To build: diff --git a/2015/endoh3/README.md b/2015/endoh3/README.md index b556973f3..8500b0993 100644 --- a/2015/endoh3/README.md +++ b/2015/endoh3/README.md @@ -2,7 +2,7 @@ Yusuke Endoh -Twitter: @mametter +Mastodon: [@mame@ruby.social](https://ruby.social/@mame) ## To build: diff --git a/2015/endoh4/README.md b/2015/endoh4/README.md index afdada9aa..cf9dd309d 100644 --- a/2015/endoh4/README.md +++ b/2015/endoh4/README.md @@ -2,7 +2,7 @@ Yusuke Endoh -Twitter: @mametter +Mastodon: [@mame@ruby.social](https://ruby.social/@mame) ## To build: diff --git a/2018/endoh1/.gitignore b/2018/endoh1/.gitignore index 15117a0a3..5a96aacaf 100644 --- a/2018/endoh1/.gitignore +++ b/2018/endoh1/.gitignore @@ -2,4 +2,5 @@ golem.gif invisible.gif output.gif prog +prog.gif smily.gif diff --git a/2018/endoh1/README.md b/2018/endoh1/README.md index 51693510c..d94de6a6e 100644 --- a/2018/endoh1/README.md +++ b/2018/endoh1/README.md @@ -1,7 +1,8 @@ # Best tool to reveal holes - Yusuke Endoh - Twitter: @mametter +Yusuke Endoh + +Mastodon: [@mame@ruby.social](https://ruby.social/@mame) ## To build: diff --git a/2018/endoh2/README.md b/2018/endoh2/README.md index 4015b5cee..f9df2f7e9 100644 --- a/2018/endoh2/README.md +++ b/2018/endoh2/README.md @@ -1,7 +1,8 @@ # Best use of python - Yusuke Endoh - Twitter: @mametter +Yusuke Endoh + +Mastodon: [@mame@ruby.social](https://ruby.social/@mame) ## To build: diff --git a/2018/ferguson/README.md b/2018/ferguson/README.md index 39b3b3a29..7f8d0e97d 100644 --- a/2018/ferguson/README.md +++ b/2018/ferguson/README.md @@ -1171,17 +1171,20 @@ requiring creativity, cleverness and novelty is a tribute to an equally creative, clever and unique dog that she was. I miss you terribly Venus but I'm so happy to have had you in my life. -But I want to also dedicate it to (and thank) my dear friend Martijn Schoemaker -whom provided me with the spark a very long time ago (and whom has stood by me -and helped me in more ways than he can know - **`#including C`**); if it wasn't -for you Martijn I wouldn't have been able to win so consider this a recursive -thank you thank you! :) I would also like to give thanks and much love to my -best and closest friend Vicky Wilmore who means the absolute world to me; thank -you for being such a wonderfully beautiful person and friend - that truly is -what 'just you' means, sweetheart, and don't you forget it! <3 Finally I would -like to thank my mother for being the best mum anyone could ask for, who's -always been here for me and whom I also inherit the keen analytical mind from. I -love you all! +But I want to also dedicate it to (and thank) my dear friend [Martijn +Schoemaker](https://www.ficture.nl) whom provided me with the spark a very long +time ago (and whom has stood by me and helped me in more ways than he can know - +**`#including C`**); if it wasn't for you Martijn I wouldn't have been able to +win so consider this a recursive thank you thank you! :) + +I would also like to give thanks and much love to my dear friend Vicky Wilmore +who means the absolute world to me; thank you for being such a wonderfully +beautiful person and friend - that truly is what 'just you' means, sweetheart, +and don't you forget it! <3 + +Finally I would like to thank my mother for being the best mum anyone could ask +for, who's always been here for me and whom I also inherit the keen analytical +mind from. I love you all! I want to also thank [Dave Burton](/winners#Dave_Burton) for acknowledging me in his [README.md]((../burton2/README.md) for his [2018/burton2](../burton2/prog.c) diff --git a/2019/endoh/README.md b/2019/endoh/README.md index a5b0aacc2..73b8280bd 100644 --- a/2019/endoh/README.md +++ b/2019/endoh/README.md @@ -1,7 +1,8 @@ # Most in need of debugging Yusuke Endoh -Twitter: @mametter + +Mastodon: [@mame@ruby.social](https://ruby.social/@mame) ## To build: diff --git a/2020/endoh1/README.md b/2020/endoh1/README.md index d2b8f4ce6..9ef2cb87f 100644 --- a/2020/endoh1/README.md +++ b/2020/endoh1/README.md @@ -1,7 +1,8 @@ # Most explosive Yusuke Endoh -Twitter: @mametter + +Mastodon: [@mame@ruby.social](https://ruby.social/@mame) ## To build: diff --git a/2020/endoh2/README.md b/2020/endoh2/README.md index 11ab35d4e..1035a8e0c 100644 --- a/2020/endoh2/README.md +++ b/2020/endoh2/README.md @@ -1,7 +1,8 @@ # Best perspective Yusuke Endoh -Twitter: @mametter + +Mastodon: [@mame@ruby.social](https://ruby.social/@mame) ## To build: diff --git a/2020/endoh3/README.md b/2020/endoh3/README.md index f43f21ec4..846aee599 100644 --- a/2020/endoh3/README.md +++ b/2020/endoh3/README.md @@ -1,7 +1,8 @@ # Most head-turning Yusuke Endoh -Twitter: @mametter + +Mastodon: [@mame@ruby.social](https://ruby.social/@mame) ## To build: diff --git a/2020/ferguson1/COMPILING.md b/2020/ferguson1/COMPILING.md index 2ac12b5a4..d0c2f8e3b 100644 --- a/2020/ferguson1/COMPILING.md +++ b/2020/ferguson1/COMPILING.md @@ -1,10 +1,10 @@ In order to successfully compile this you will need a C compiler that supports C99+ and ncurses; note that for some platforms (e.g. Red Hat based Linux) you will need two different packages: the library itself but also the dev package -that has the header files etc. If you use the Makefile obviously you need `make' +that has the header files etc. If you use the Makefile obviously you need `make` too. -In gameplay.md I show how to easily customise the colours, set up +In [gameplay.md](gameplay.md) I show how to easily customise the colours, set up different gameplay modes and various other things. The troubleshooting.md and terminals.md as well as bugs.md include a variety of information should you run into trouble. @@ -33,7 +33,9 @@ I imagine that it works for 32-bit systems but I do not know for sure. You should be able to get the compiler with: - sudo xcode-select --install +```sh +sudo xcode-select --install +``` You don't need Xcode itself and it appears that the command line tools (as above should install) already has ncurses so there shouldn't be anything else that @@ -51,10 +53,15 @@ you want to use the Makefile) to compile and link this entry. With Fedora more recent versions there's the `dnf` package manager but I cannot help with any of the GUI installers since I don't use them. Something like: - sudo dnf install ncurses-devel ncurses make gcc +```sh +sudo dnf install ncurses-devel ncurses make gcc +``` - Or - # dnf install ncurses-devel ncurses make gcc +or + +```sh +# dnf install ncurses-devel ncurses make gcc +``` # Portability: CentOS @@ -62,20 +69,29 @@ Just like Fedora you will need `gcc`, `ncurses`, `ncurses-devel` (and if you want to use the Makefile `make`). CentOS uses `yum` and CentOS 8 uses `dnf`. So: - sudo yum install ncurses-devel ncurses make gcc +```sh +sudo yum install ncurses-devel ncurses make gcc +``` - Or - # yum install ncurses-devel ncurses make gcc +or -Or - sudo dnf install ncurses-devel ncurses make gcc +```sh +# yum install ncurses-devel ncurses make gcc +``` - Or +or - # dnf install ncurses-devel ncurses make gcc +```sh +sudo dnf install ncurses-devel ncurses make gcc +``` +or -You can also use Clang to compile. +```sh +# dnf install ncurses-devel ncurses make gcc +``` + +You can also use clang to compile (which is what gcc actually is under macOS). # Compilation notes diff --git a/2020/ferguson1/HACKING.md b/2020/ferguson1/HACKING.md index 4b4e19e29..e75791a79 100644 --- a/2020/ferguson1/HACKING.md +++ b/2020/ferguson1/HACKING.md @@ -1,4 +1,11 @@ -## Warning / caveat about this document +# About this document + +In this document I provide information to the herpetologist hackers to help them +modify certain things and add features for their studying of snakes. Or if +you prefer you can be the snake studying the herpetologist. Whichever character +you prefer to play doesn't really matter. + +# Warning / caveat about this document WARNING: There are some things cited in this document that are no longer correct, might be misleading or otherwise not clear. This is both intentional @@ -7,21 +14,17 @@ something specific. Put another way just because the table says something doesn't mean it's the whole truth: no misleading comments but misleading document that talks about some parts of the code! -In this document I provide information to the herpetologist hackers to help them -to modify certain things and add features for their studying of snakes. Or if -you prefer you can be the snake studying the herpetologist. Whichever character -you prefer to play doesn't really matter. - Please do not assume that just because something is in this file means that it's -complete or will work without any changes. As I have changed the game over -development stages some features have been dramatically changed and some of -these ideas could be incompatible now or otherwise impractical. Also you might -find in fact that some of these leave more questions than answers (e.g. some -require making decisions for specific problems one might encounter)! +complete or will work without any changes (see above). As I have changed the +game over development stages some features have been dramatically changed and +some of these ideas could be incompatible now or otherwise impractical. Also you +might find in fact that some of these leave more questions than answers (e.g. +some require making decisions for specific problems one might encounter)! With that said here's the C sibilancy (the herpetologist programmer's and snake's syllabary) for all snake and herpetologist programmers alike. +# Modifying and adding additional features to the code * Modifications @@ -61,14 +64,14 @@ snake's syllabary) for all snake and herpetologist programmers alike. - Max times the bug evades before game over -* MODIFICATIONS +# Modifications Here I include information on modifying the game in various ways depending on the preference of the herpetologist (or if you prefer you can be the snake studying the herpetologist). -# Modifying the colours +## Modifying the colours As I already said I provided a script that prompts you for colours and then compiles the game with those colours (default if invalid input). @@ -82,78 +85,88 @@ and background. To change the colours use the snake-colours.sh or play.sh scripts. Hit enter for defaults if you don't want to change the colour. -# Background colour of the game field +## Background colour of the game field I prefer black backgrounds but this is the basic idea behind changing it. You initialise a pair (make it 5 so as to not interfere with the script customisability) and then you use the bkgd() function with the colour pair. Something like this: - init_pair(5, COLOR_BLACK, COLOR_WHITE); - bkgd(COLOR_PAIR(5)); +```c +init_pair(5, COLOR_BLACK, COLOR_WHITE); +bkgd(COLOR_PAIR(5)); +``` I played with this after winning and I came across some problems with colours but that changes the background of the program anyway. The standard colour identifiers are: - COLOR_BLACK - COLOR_RED - COLOR_GREEN - COLOR_YELLOW - COLOR_BLUE - COLOR_MAGENTA - COLOR_CYAN - COLOR_WHITE +```c +COLOR_BLACK +COLOR_RED +COLOR_GREEN +COLOR_YELLOW +COLOR_BLUE +COLOR_MAGENTA +COLOR_CYAN +COLOR_WHITE +``` -See Linux Journal for more information: - - https://www.linuxjournal.com/content/programming-color-ncurses for more details). +See Linux Journal for more information article + for more +details. -# Modifying the characters for the wall, bug and snake +## Modifying the characters for the wall, bug and snake For the wall, bug and snake body characters you can replace the following in the -source code (include the single quotes) respectively: +source code (**include the single quotes!**) respectively: - '#' +``` +'#' - '*' +'*' - 'o' +'o' +``` -# Modifying input keys +## Modifying input keys Let's say you don't want to use arrow keys or you don't have arrow keys. Instead -you might want the keys 'l', 'r', 'u' and 'd' for the directions. Find the case +you might want the keys `l`, `r`, `u` and `d` for the directions. Find the case statements: - KEY_LEFT - KEY_RIGHT - KEY_UP - KEY_DOWN +```c +case KEY_LEFT: +case KEY_RIGHT: +case KEY_UP: +case KEY_DOWN: +``` -Replace KEY_LEFT with: +Replace `KEY_LEFT` with: - 'l' +```c +'l' +``` -(Yes the single quotes matter) - -And do the same thing for the other directions too. If you want more than one +and do the same thing for the other directions too. If you want more than one key e.g. the arrow keys and the letters just add another case statement e.g. for left it might be: - case KEY_LEFT: case 'l': +```c +case KEY_LEFT: case 'l': +``` + +Yes the single quotes matter. You can do similar for the other input keys. +Please note that modifier keys like ctrl aren't detectable or at least I'm +unaware of how to do so. -You can do similar for the other input keys. Please note that modifier keys like -ctrl aren't detectable or at least I'm unaware of how to do so. +## Modifying the status/score line (table of variables/stats below) - -# Modifying the status/score line (table of variables/stats below) - -* SPOILER WARNING +### SPOILER WARNING Below I give a table of some variables/expressions along with the data types and their respective format specifiers of the data. Originally it was a lot more @@ -167,11 +180,15 @@ different sets. Please also be aware that if you don't want any information you must set it to the below at the very least; defining it without a value is not enough (it amounts to the parameters to a printf call): - #define J " " ); +```c +#define J " " ); +``` If you don't care about brief displays of 'o' at 0,0 you can just have: - #define J ""); +```c +#define J ""); +``` That's the bare minimum. Notice also that it's been a long while since I've tested this part but I think this is right. @@ -191,7 +208,9 @@ coordinates of where the snake is plus the other things that are there (a number of which were added over time). Obviously this would take many bug sized bytes (bites) even once let alone twice! Thus I made it into a define: - #define J Z(X:%d/%d Y:%d/%d S:%zu/%zu B:%zu\n), Y, y[-2], X,*y,A,g, c); +```c +#define J Z(X:%d/%d Y:%d/%d S:%zu/%zu B:%zu\n), Y, y[-2], X,*y,A,g, c); +``` With the table below you can show a variety of other variables/statistics. @@ -199,7 +218,7 @@ There's another reason for changing this line though: depending on the terminal width the line could cover the top wall; this can even happen only part of the game because the line length is not constant: most of the variables change throughout the game play and as these are displayed the length of the line -changes. Use `make test' to get an estimate (it's not perfect). +changes. Use `make test` to get an estimate (it's not perfect). This is not the fault of my entry but rather how text wraps. But this is another reason it's easy to change: if the terminal size is too short then you can @@ -215,78 +234,83 @@ For an example this would only include the size of the snake and the number of bugs eaten (I think I have this correct; I've made many changes to the point of not wanting to mess with anything that's unnecessary): - #define J Z(SIZE: %zu BUGS: %zu\n), A, c); +```c +#define J Z(SIZE: %zu BUGS: %zu\n), A, c); +``` More generally the following expressions and data types (with format specifiers) come to mind as information that might be of interest. - DESCRIPTION EXPRESSION TYPE FORMAT NOTES - SPECIFIER + DESCRIPTION EXPRESSION TYPE FORMAT SPECIFIER + + Snake size A size_t %zu + + Y coordinate Y int %d + of snake head + + X coordinate X int %d + of snake head + + Max snake size g size_t %zu + + Bugs eaten c size_t %zu + + Bug line (Y) *U int %d + + Bug column (X) *V int %d + + Snake size A size_t %zu + + Growth size (per N size_t %zu + bug) + - Snake size A size_t %zu - - Y coordinate Y int %d - of snake head - - X coordinate X int %d - of snake head - - Max snake size g size_t %zu - - Bugs eaten c size_t %zu - - Bug line (Y) *U int %d - - Bug column (X) *V int %d - - (Initial) Snake size A size_t %zu - - Growth size (per N size_t %zu - bug) - - -# Make it so the snake starts at a random location +## Make it so the snake starts at a random location Quite simply change: - X = H / 2; Y = *x / 2; +```c +X = H / 2; Y = *x / 2; +``` To be something like: - X = R(1,H-1); - Y = R(2,*x-1); +```c +X = R(1,H-1); +Y = R(2,*x-1); +``` Or whatever you might want it to be... (question to answer: will this work at all? You decide!) -* ADDITIONS (+) +# Additions (+) Here are some things you could add (including a bit of code). -# Health (and/or Lives) +## Health (and/or Lives) This was something I thought of a number of times but I opted for other features instead. Here are some ideas on how one might choose to implement something like this. Or maybe it's more like what sorts of things do you have to consider and answer? -(1) If the snake runs back into itself - thus dying - the snake would actually -be slithering inside itself (a rather creepy thought - though they sort of do -when they shed their skin). How then would the lives be of any value? If that -would constitute as running into itself wouldn't it very quickly lose all lives? +0. If the snake runs back into itself - thus dying - the snake would actually be +slithering inside itself (a rather creepy thought - though they sort of do when +they shed their skin). How then would the lives be of any value? If that would +constitute as running into itself wouldn't it very quickly lose all lives? -I can think of a number of ways to answer this question: by defining specific -rules (as in what would be allowed and what wouldn't be) and also by when to -decrement the lives. + I can think of a number of ways to answer this question: by defining + specific rules (as in what would be allowed and what wouldn't be) and also + by when to decrement the lives. -(2) If the snake hits a wall and it's not allowed to where would the snake be +1. If the snake hits a wall and it's not allowed to where would the snake be placed? This is similar to (1) but maybe not as many things to consider. -(3) Should the snake lose its size? WHAT does having another life even MEAN? +2. Should the snake lose its size? WHAT does having another life even MEAN? -(4) Do you want (you do not necessarily need) a new variable that says how many +3. Do you want (you do not necessarily need) a new variable that says how many lives you want? Either way probably be good that it can be specified by the player. @@ -305,12 +329,12 @@ some other complications. You could do similar for health only maybe the size of the snake decreases or you use the variable you would have used for lives to be health instead. -Vital issue to resolve: Where is the snake? And if the snake size is decreased +Vital issue to resolve: where is the snake? And if the snake size is decreased will you be careful enough that you don't run into the snake where it actually isn't? -# Saving the game +## Saving the game A few things would have to be done to do this. Maybe more than a few: some decisions and some code. @@ -329,8 +353,8 @@ the number of bugs eaten so far. Alternatively you could have the bug simply be placed somewhere where the snake isn't after replacing (can you replace something with itself?) the snake. -Question: Do you have to save the WALLS and other environmental variables? -You wouldn't have to but you could: If you didn't it would mean that the player +Question: do you have to save the WALLS and other environmental variables? +You wouldn't have to but you could: if you didn't it would mean that the player could change the growth size on another run for example, or they could disable or enable a feature. @@ -355,40 +379,43 @@ It might seem like a difficult task but it's actually not that difficult. It didn't take much time for me to do something like this: as far as saving and loading the values and even setting up ncurses: I just didn't go beyond that. -Tip: Don't try scr_dump()/scr_restore()/scr_init()/scr_set(). After a quick +Tip: **DON'T TRY** `scr_dump()`/`scr_restore()`/`scr_init()`/`scr_set()`. After a quick test in the way I have things set up it seems to cause some problems (also -scr_dump() quits the program). +`scr_dump()` quits the program). You would have to instead identify that restoring is requested, then read in the file (including the coordinates) and then populate the snake arrays, drawing it on screen. -# Different types of walls +## Different types of walls The game has two modes with walls: if you run into it the game is over (you die) OR you go through it and come out on the opposite side. There certainly are other possibilities though. Here I give some ideas that could be implemented (and one I have some code for). -# Different types of walls: Blockades +### Different types of walls: Blockades -Instead of the snake either dying or going through and out on the other side -what if it's just that the snake is momentarily dazed and unable to move again -until it comes round sort of like what happens with some people who pay more -attention to their ruddy phone instead of where they're walking (even when -crossing a busy street!). +I did this once before as an experiment so it can work fine: let's say instead +of the snake either dying or going through and out on the other side what if +it's just that the snake is momentarily dazed and unable to move again until it +comes round sort of like what happens with some people who pay more attention to +their ruddy phone instead of where they're walking (even when crossing a busy +street!). -If you look at the walls code you will see a ternary operator for both X and Y +If you look at the walls code you will see a ternary operator for both `X` and `Y` coordinates. This of course is very different now but the idea remains the same: - if (p && !(*O>=O[1]||H>=M(1))) - { - if (X<1||X>=H) - X = X<1?H-1:1; - if (Y<2||Y>=*O) - Y = Y<2?*O-1:2; - } +```c +if (p && !(*O>=O[1]||H>=M(1))) +{ + if (X<1||X>=H) + X = X<1?H-1:1; + if (Y<2||Y>=*O) + Y = Y<2?*O-1:2; +} +``` You can ignore the first if if you like; I'm not going to explain that part. The @@ -399,9 +426,11 @@ coordinates to the correct new location. If however you wanted the walls to act as a barrier you could do something like this instead (omitting the inner if statements here): - X=X<1?1:*H-1; +```c +X=X<1?1:*H-1; - Y=Y<2?2:*O-1; +Y=Y<2?2:*O-1; +``` Again though that's just the idea; the code is dramatically different. The above incidentally is not even complete. @@ -421,22 +450,25 @@ other words the snake will just appear to be not moving as if the game had been paused. -# Diagonal movement +## Diagonal movement I said this is impractical so how could it be done? Well you have to decide which keys would take you up and right, up and left, down and right or down and left. The trouble is ncurses can't detect both right and up at the same time. -Besides that though it would only be a matter of updating both Y and X +Besides that though it would only be a matter of updating both `Y` and `X` coordinates rather than just one or the other. That's easy enough to do. The only impractical part of this is deciding the keys and unfortunately rule 2b (and probably 2b) would have been broken and so have no chance of winning (now -that I won it's too much effort and I've forgotten some of the stuff too to say +that I won it's too much effort and I've forgotten most of the stuff too to say nothing of getting the format right). -Anyway it's just a matter of updating both X and Y. But what about going through -walls mode? Does it matter? I'll let you figure it out! +Anyway it's just a matter of updating both `X` and `Y`. But what about going +through walls mode? Does it matter? I'll let you figure it out! -# Special abilities +Looking back at the missing features, this is the feature I wanted more than any +other. + +## Special abilities Could the snake jump over itself if it wanted to? How would this be implemented? The head would simply be moved one beyond but then you would have to keep track @@ -446,7 +478,7 @@ actually includes it! Then it would only be a matter of deciding what key does what. -# Obstacles +## Obstacles Similar to walls only that it's inside the field. You would have to consider the behaviour of running into the obstacles: should the snake die? Should it @@ -457,7 +489,7 @@ character. Also to make it simpler if the walls are passable then so too would be the obstacles; else you would die (or if you had health/lives then those would apply). -# More than one bug +## More than one bug The main thing to consider would be the test if the snake has eaten a bug would have to check an array (and: how big? Where does the size come from?) as well as @@ -466,14 +498,14 @@ meaning that if you run into a bug spot that has more than one bug you would eat that many bugs). -# Power-ups +## Power-ups You would need to decide what power-ups exist, what they do, how many can there be (and how many can the snake have at one time), what makes them show up plus you would have to add code to handle the power-ups. -# Snakeskin shedding (becoming an obstacle) +## Snakeskin shedding (becoming an obstacle) I.e. at some point the snake would split back to some (arbitrary) size but then the snakeskin left would act as the snake in the sense that if the snake runs @@ -483,18 +515,18 @@ slithered out. But that would fill the screen very quickly of course. Maybe the snakeskin has some other purpose? -# Snake moves faster over time +## Snake moves faster over time -In the game Surround you have no control over the speed. I believe there are -five different speed levels but the player has no control over it except the -drawing mode. It would be possible to make it so the snake moves faster over -time. How often and by what amount would probably vary but importantly it would -need to not go so fast there's no controlling - or go below 0 which puts it in -blocking mode. Probably it would be that it gets faster up to a certain per cent -of the original speed so that it doesn't get too fast. But even that would have -to be customisable. +In the game [Surround](https://en.wikipedia.org/wiki/Surround_(video_game) you +have no control over the speed. I believe there are five different speed levels +but the player has no control over it except the drawing mode. It would be +possible to make it so the snake moves faster over time. How often and by what +amount would probably vary but importantly it would need to not go so fast +there's no controlling - or go below 0 which puts it in blocking mode. Probably +it would be that it gets faster up to a certain per cent of the original speed +so that it doesn't get too fast. But even that would have to be customisable. -# Max times the bug evades before game over +## Max times the bug evades before game over Basically so that the player is on a time schedule of sorts. The same could be done for maximum number of movements before game over. These would both be diff --git a/2020/ferguson1/Makefile b/2020/ferguson1/Makefile index 495e147c0..a1663a1eb 100644 --- a/2020/ferguson1/Makefile +++ b/2020/ferguson1/Makefile @@ -113,8 +113,8 @@ ENTRY= ferguson1 PROG= prog # OBJ= ${PROG}.o -DATA= COMPILING.md HACKING.md bugs.html bugs.md cake.jpg cannibalism.log \ - chocolate-cake.html chocolate-cake.md crazy.log gameplay.html gameplay.md \ +DATA= COMPILING.md HACKING.md bugs.html bugs.md cake.jpg cannibalism.log.md \ + chocolate-cake.html chocolate-cake.md crazy.log.md gameplay.html gameplay.md \ halfwidth_vs_fullwidth.png ioccc-cake.jpg play.sh prog.2.c prog.3-j.c \ prog.3.c snake-colours.sh snake.1 spoilers.html spoilers.md \ termcaps.c terminals.html terminals.md troubleshooting.html troubleshooting.md diff --git a/2020/ferguson1/README.md b/2020/ferguson1/README.md index 405a57b74..e9b15cac5 100644 --- a/2020/ferguson1/README.md +++ b/2020/ferguson1/README.md @@ -15,64 +15,69 @@ make ```sh WAIT=N WALLS=[01] EVADE=N SIZE=N MAXSIZE=N GROW=N SHEDS=N SHED=N CANNIBAL=[01] ./prog -# Start pressing some arrow keys +# start pressing some arrow keys ``` -Variables: +where `N` is a number and `[01]` is either `1` or `0` (or more correctly zero +and non-zero). -* WAIT +### Variables: + +* **`WAIT`** positive or negative integer that changes how long to wait for a key press prior to moving again. < 0 blocks which allows for complete control over movement at your own pace. Default - 231; you can move faster by holding down an arrow key. + 231; you can move faster by holding down or rapidly pressing an + arrow key. -* WALLS - whether the walls are passable or impassable (default - passable). 0 means impassable; 1 passable. +* **`WALLS`** + whether the walls are passable or impassable. Default passable, + 1; 0 makes walls impassable where you die if you hit a wall. -* EVADE +* **`EVADE`** how many movements the Snake moves before the bug (well - insect; see notes below about why bugs) is will move to - another location on the field. + insect; see notes below about why bugs) will move to + another location in the field. Default 300; 0 disables. -* SIZE +* **`SIZE`** initial size of the Snake. Note that it grows by one per move so at the default 5 it will not initially be 5 - characters long! < 0 is an immediate win. + characters long! < 0 is likely an immediate win. -* MAXSIZE +* **`MAXSIZE`** the maximum size the Snake can become before the game is won. < 0 is the maximum size based on terminal dimensions; any other size will be capped based on the terminal - dimensions to prevent problems. + dimensions to prevent problems. Note that when **`SIZE+GROW >= + MAXSIZE`** you win _before_ you grow to the full size! -* GROW - size to grow every time you eat a bug. Negative values are - allowed! This creates for fun gameplay modes with enough - creativity. See [gameplay.html](gameplay.html) for some - examples. +* **`GROW`** + size to grow every time you eat a bug. Default 5; negative + values are allowed. 'Negativity' creates for fun gameplay modes with + enough creativity. See [gameplay.html][] ([gameplay.md][] on + GitHub) as well as [play.sh](play.sh) for some examples. -* SHED - every SHED movements you will grow (> 0), shrink (< 0) or - not at all (0) by the SHEDS value. Again with creativity you - can create some fun gameplay modes. - - NOTE: SHED and SHEDS is actually a misnomer; see notes +* **`SHED`** + every **`SHED`** movements you will grow (> 0), shrink (< 0) or + stay the same length (0) by the **`SHEDS`** (below) value. Again + with creativity you can create some fun gameplay modes. NOTE: + the concept of shedding in this game is a misnomer; see notes below. -* SHEDS - every SHED movements will impact what this value means: grow - (> 0), shrink (< 0) or not at all (0). Again with creativity - you can create some fun gameplay modes here. For instance - you can grow upon eating a bug but shrink every SHED - movements and it's a battle of whether you win by SIZE < 0 - or SIZE >= MAXSIZE. See play.sh for examples. - NOTE: SHED and SHEDS is actually a misnomer; see notes - below. +* **`SHEDS`** + every **`SHED`** movements will impact what this value means: grow + (> 0), shrink (< 0) or not at all (0). Exception: if the snake + eats a bug the counter isn't incremented. Again with creativity + you can create some fun gameplay modes here. For instance you + can grow upon eating a bug but shrink every **`SHED`** movements + and then it's a battle of whether you win by **`SIZE < 0`** or + **`SIZE >= MAXSIZE`**. See [play.sh](play.sh) for examples. + NOTE: the concept of shedding in this game is a misnomer; see + notes below. -* CANNIBAL +* **`CANNIBAL`** whether you can go through the Snake or not. Default is 0 - (cannot). + (cannot - die if you try). @@ -107,27 +112,27 @@ This game has a number of configurable pitfalls including walls and snakes. There is a good deal of useful documentation that is provided with this entry: -* [gameplay.html][] +* [gameplay.html][] ([gameplay.md][] on GitHub) -Documented game *features*! +Documented game *features* and gameplay modes! -* [terminals.html][] +* [terminals.html][] ([terminals.md][] on GitHub) Information about terminal capabilities, dimensions (setting and how to restore sanity if it causes any problems) as well as colours (limitations etc.). -* [troubleshooting.html][] +* [troubleshooting.html][] ([troubleshooting.md][] on GitHub) Workarounds for various game *features* -* [bugs.html][] +* [bugs.html][] ([bugs.md][] on GitHub) Bugs and things that might seem like bugs but are not. -* [chocolate-cake.html][] +* [chocolate-cake.html][] ([chocolate-cake.md][] on GitHub) Because most of us could use some *Double-layered Chocolate Fudge Cake*! -* [spoilers.html][] +* [spoilers.html][] ([spoilers.md][] on GitHub) Read ***ONLY*** if you really must give up trying to de-obfuscate! @@ -137,58 +142,34 @@ Read ***ONLY*** if you really must give up trying to de-obfuscate! Snake has two cheat modes (passable walls and self [cannibalism]), a drawing (or practising) mode, *can play by itself (**and win!**)*, is coloured (included -[snake-colours.sh][] and [play.sh][] scripts compile in player-selected -colours) and there are many other play modes (many more can be devised with the -imagination and the environmental variables; see [gameplay.html][] for many -examples) and options. You can pause and there's even a built-in test unit for -some features! The following variables change the game in the following ways -(all can be combined): +[snake-colours.sh][] and [play.sh][] scripts compile in player-selected colours) +and there are many other play modes (many more can be devised with the +imagination and the environmental variables; see [gameplay.html][] +([gameplay.md][] on GitHub) for many examples and [play.sh][] for preconfigured +modes) and options. You can pause and there's even a built-in test unit for +some features! The variables mentioned in the to run section at the top of this +file modify the behaviour of Snake. +Here are some other features of the game: -* The speed of the snake: how many milliseconds to **WAIT** for input before - moving; *default 231 milliseconds*. You can move faster by pressing a - direction key quicker or even holding it down. - -* If the bug (to eat) will move (**EVADE**) after user-specified number of snake - moves (*default 300, 0 disables*). - -* If the snake can go through **WALLS** (coming out at the opposite wall) - (*default 1, yes*). - -* If the snake can go through itself (**CANNIBAL**) (*default 0, no*). - -* The initial **SIZE** of the snake (*default 5*). Note that it grows one by - each movement so even if you start at 5 it will take some movements before - you are the full length. - -* The size the snake must become in order to win the game (**MAXSIZE**, *default 997*). - -* How much to **GROW** each time a bug is eaten (*default 5*, can be negative). - -* How many moves (**SHED**, *default 0, disabled*) before 'stretching' (grow) - (**SHEDS**, *default 5*; can be negative). This is how snakes grow in the wild so is a - misnomer here because snakes don't grow in the manner that the original - Snake game was designed. - - - Exception: if the bug is eaten the counter isn't incremented. - -* A drawing/practising mode (**WAIT** < 0 makes `timeout()` set blocking read). +* A drawing/practising mode (**`WAIT`** < 0 makes `timeout()` block). * Computer plays the game (**WAIT=0**). - **EPILEPSY/STIMULATION OVERLOAD WARNING** included in the relevant - section (this goes for a low **EVADE** value too). + section (this goes for a low **`EVADE`** value too). * Grow-Shrink mode (Positive and Negative Winning) mode (see - [gameplay.html][] for more details). + [gameplay.html][] ([gameplay.md][] on GitHub) for more details). * The dimensions of the game (this is actually a terminal thing but I document - how to do this and its potential pitfalls) (**LINES** , **COLUMNS**). + how to do this and its potential pitfalls) (**`LINES`** , **`COLUMNS`**). There are no complicated command line invocations; it's just a matter of passing into the game descriptively named variables and I include a script that sets up -many different gameplay modes (see [gameplay.html][] and [play.sh][]). +many different gameplay modes (see [gameplay.html][] ([gameplay.md][] on GitHub) +and [play.sh][]). -The [gameplay.html][] file has all the information on +The [gameplay.html][] ([gameplay.md][] on GitHub) file has all the information on what the game looks like, how to play, the different types of modes (that I have thought of so far) including all those in the above list. Along with the [play.sh][] and [snake-colours.sh][] scripts it's probably the most important @@ -202,22 +183,22 @@ suggestions (that I don't document so as to not spoil them). You can pass in environmental variables to both scripts though obviously some will conflict with different options in play.sh. -Probably just as important is [chocolate-cake.html][] with an old but wonderful -recipe (because the judges love chocolate and who can blame them? - also it goes -with one of the IAQs I include later). +Probably just as important is [chocolate-cake.html][] ([chocolate-cake.md][] on +GitHub) with an old but wonderful recipe (because the judges love chocolate and +who can blame them? - also it goes with one of the IAQs I include later). -The [troubleshooting.html][] file has some advice on potential problems (and -things that might appear to be problems at first glance but are not) that I have -thought of or encountered. +The [troubleshooting.html][] ([troubleshooting.md][] on GitHub) file has some +advice on potential problems (and things that might appear to be problems at +first glance but are not) that I have thought of or encountered. -The [terminals.html][] has a variety of information specific to terminals from -input/directions, dimensions, sanity and colours: a sort of troubleshooting -guide for terminals with some additional information. +The [terminals.html][] ([terminals.md][] on GitHub) has a variety of information +specific to terminals from input/directions, dimensions, sanity and colours: a +sort of troubleshooting guide for terminals with some additional information. -The [spoilers.html][] has a variety of information including some of the -obfuscation techniques and a bit of how it works. +The [spoilers.html][] ([spoilers.md][] on GitHub) has a variety of information +including some of the obfuscation techniques and a bit of how it works. -The [bugs.html][] has a list of known bugs and things that +The [bugs.html][] ([bugs.md][] on GitHub) has a list of known bugs and things that look like bugs but aren't as well as documenting a built-in test unit for some features. @@ -228,19 +209,22 @@ though much of it is what's also above). To render try: man ./snake.1 ``` -The [COMPILING][] file has a few portability notes and the [HACKING][] file has -some information on how one might modify things, things that could be -implemented (and how to/how not to go about some of the things) as well as some -other information on the entry (some of which is deliberately not true - a -variation of misleading comments). These files are probably insignificant. +The [COMPILING.html][] ([COMPILING.md][] on GitHub) file has a few portability +notes and the [HACKING.html][] ([HACKING.md][] on GitHub) file has some +information on how one might modify things, things that could be implemented +(and how to/how not to go about some of the things) as well as some other +information on the entry (some of which is deliberately not true - a variation +of misleading comments). These files are probably insignificant. I have more information about this entry at -[https://ioccc.xexyl.net/2020/snake][]. +. + +As noted for the files I recommend looking at the html files with a browser +unless on GitHub in which case I recommend the markdown files; this particularly +goes for the gameplay, bugs, terminals, troubleshooting ones along with the most +important one, chocolate cake. Most important for the cake as the formatting is +very important. -For the files I recommend looking at the html files with a browser; this -particularly goes for the [gameplay.html][], [bugs.html][], [terminals.html][] -and [troubleshooting.html][] - along with the most important one -[chocolate-cake.html][]. @@ -288,7 +272,7 @@ and [troubleshooting.html][] - along with the most important one took fewer bytes and the negative shedding is a positive consequence of unsigned arithmetic. -On a more serious note look at [bugs.html][]. +On a more serious note look at [bugs.html][] ([bugs.md][] on GitHub). ### NAQs/IAQs (Never/Infrequently Asked Questions) @@ -308,7 +292,8 @@ everything? That's an unintentional lie; I thought it was everything but I implemented many new things after that. In fact I have numerous times thought I was done only to have added yet another feature - or two or three or more! -Second is the old Atari game [Surround][]. There were a few modes as I recall. +Second is the old Atari game [Surround][] (according to Wikipedia it might even +be the origin of Snake itself). There were a few modes as I recall. The object of the game was to surround your opponent so that they would run into you, the wall or themselves. The opponent was either the computer or another player. @@ -318,11 +303,11 @@ likewise). There was also a drawing mode where you could just move round making different designs though that this is in my entry is a happy coincidence (because `timeout()` will block when it gets a negative value). It's true that in my Snake it's not quite the same but it's close enough. Perhaps it can be -made more like Surround if it grows every movement but then depending on the max +made more like [Surround][] if it grows every movement but then depending on the max size of the snake the game might be over fairly quickly (I don't remember how -it was done in Surround). +it was done in [Surround][]). -In Surround each move you made you would grow in size by one. This is what +In [Surround][] each move you made you would grow in size by one. This is what inspired the shedding mode. Anyway I always loved the game and it's similar to Snake in several ways. @@ -427,7 +412,7 @@ And if you're a show-off you can try: - Do more than one or all of the above at the same time (the longer the snake becomes the more often you should do these things). - Eat a [great chocolate cake][]. Actually you should do that whether you're - trying to show off or not. Sleep, bathe, eat chocolate cake, play Snake, eat + trying to show off or not. Sleep, bath, eat chocolate cake, play Snake, eat chocolate cake, play Snake, sleep, ... For a great recipe see below. But if that's not enough I don't know what to tell you other than suggest that @@ -441,7 +426,7 @@ a pun and every pun deserves to be shed). They grow through a process called moulting - shedding their skin (other creatures also moult). This takes place over some days and unlike humans snakes never stop growing (though growth slows down as they mature). I chose the -variables **SHED** and **SHEDS** for simplicity and because the words are +variables **`SHED`** and **`SHEDS`** for simplicity and because the words are shorter. I don't like the words because it's rather a misnomer but what I had chosen before was longer - STRETCH and STRETCHES. @@ -461,10 +446,10 @@ when other implementations don't have it this way. There are a few reasons. First is that the friend's implementation had it that way and it had been a long time since I had played it (if I ever did? I don't know now: I played so many -games over the years and the game most alike it that I played is Surround, as +games over the years and the game most alike it that I played is [Surround][], as below). -It also is the way it is in Surround. +It also is the way it is in [Surround][]. It makes cannibalism mode very interesting. @@ -481,17 +466,18 @@ walls passable and not worry about dying. Why yes I do! So good in fact that even my late stepmum who didn't even like chocolate (except white chocolate) loved this cake. It's a double-layered -chocolate fudge cake. See the file [chocolate-cake.html][] for the recipe. -Note that it's a complicated but it's well worth it! +chocolate fudge cake. See the file [chocolate-cake.html][] +([chocolate-cake.md][] on GitHub) for the recipe. Note that it's a complicated +but it's well worth it! -I included it in all my entries this year because if any of them won more people +I included it in both of my entries this year because if any of them won more people can have this recipe; also it might help remind the judges that they really should have their cook bake it so they can all - including the cook should they also like chocolate - enjoy the cake whilst judging (and otherwise - it's a big cake and very rich). Sadly they didn't get to enjoy it during their judging due to the pandemic but maybe next time (or they can do on their own). -Do make sure to pay attention to all notes! +**Do make _SURE_ that you pay attention to _ALL_ notes!** ##### Reiterating the notes about the cake and the icing @@ -502,7 +488,8 @@ use the refrigerator or else air conditioner to cool down the place. This might or might not work well enough. - Do **NOT** use imitation vanilla! - Do **NOT** use butter even if you think it'll come out better; it will come -out bad! +out bad! Many people have made this mistake 'because they know better'. You've +been warned. - Pay attention to the rest of the notes as well! They're crucial. @@ -512,13 +499,13 @@ out bad! I submitted three Snake versions; these are the other layouts for those few (more likely none) who are interested to see them. -The prog.2.c has more digraphs but I think no other significant differences. +The [prog.2.c](prog.2.c) has more digraphs but I think no other significant differences. -The prog.3.c is in a more artistic layout (a backwards S), has at least one +The [prog.3.c](prog.3.c) is in a more artistic layout (a backwards S), has at least one additional obfuscation technique (see spoilers) but it also has more digraphs and as the judges said they feel that digraphs are dated so that's probably why -they chose the first layout. The prog.3-j.c version is prog.3.c with a shorter J -define. +they chose the first layout. The [prog.3-j.c](prog.3-j.c) version is +[prog.3.c](prog.3.c) with a shorter `J` macro. The prog.alt.c version is the one that allows for customising the bug colour and it's used in both [snake-colours.sh][] and [play.sh][]. It also calls `erase()` @@ -530,24 +517,30 @@ both do. ### Winning thoughts, dedications and thanks Once again I'm honoured to win along with some of the other veterans who I have -a huge amount of respect for; there's Don Yang, Dave Burton, Yusuke Endoh and -Edward Giles all of whom are amazing programmers. I'm especially proud to win -besides Dave Burton and Yusuke Endoh but Don Yang and Edward Giles too. +a huge amount of respect for; there's [Don Yang](/winners.html#Don_Yang), [Dave +Burton](/winners.html#Dave_Burton), [Yusuke Endoh](/winners.html#Yusuke_Endoh) +and [Edward Giles](/winners.html#Edward_Giles) all of whom are amazing +programmers. I'm especially proud to win besides Dave Burton and Yusuke Endoh +but Don Yang and Edward Giles too. -But there are some others who I don't remember like Ilya Kurdyukov (who's -offered a lot of interesting thoughts on Snake and who plans to have his own -version after the entries are published), Nathan Otterness, Nicholas Carlini -(whose entry is an absolutely brilliant abuse of printf - and I totally agree -with the judges remarks that your entry is so novel that it'll be worth special -mention in the future Best of IOCCC list!) and tsoj too. +But there are some others who I don't remember like [Ilya +Kurdyukov](/winners.html#https://en.wikipedia.org/wiki/Signals_intelligence#World_War_II) +(who's offered a lot of interesting thoughts on [Snake](../ferguson1/prog.c) and +who plans to have his own version after the entries are published), [Nathan +Otterness](/winners.html#Nathan_Otterness), [Nicholas +Carlini](/winners.html#Nicholas_Carlini) (your entry is an absolutely brilliant +abuse of `printf` - and I totally agree with the judges remarks that your entry +is so novel that it'll be worth special mention in the future Best of IOCCC +list!) and [tsoj](/winners.html#_tsoj) too. Well done and congratulations to all of you again! Thank you for submitting the wonderful entries and I'm honoured to have my two entries beside yours! To Dave Burton I thank you for your wonderful comments as well as pointing out -that even with prog.alt.c it probably would be better to make use of the alt -target instead of naming prog.c prog.alt.c. You're quite right, I had thought -of it but you brought it up so I could correct it. Much appreciated mate. +that even with [prog.alt.c](prog.alt.c) it probably would be better to make use +of the alt target instead of naming prog.c prog.alt.c. You're quite right, I had +thought of it but you brought it up so I could correct it. Much appreciated +mate. I would like to dedicate this entry to my wonderful mum Dianne Ferguson whom I love with all my heart and soul <3 Thank you for being the best mother @@ -558,13 +551,14 @@ mother. I also want to dedicate this to Vicky Wilmore who has given me a lot of love the past few years and who was there for me in some very dark times. Thank -you Vicky sweetheart from the bottom of my heart and soul. +you Vicky sweetheart from the bottom of my heart and soul xxx -I would like to thank my dear friend Martijn Schoemaker for encouraging me in my -programming over the years and who I owe a great deal to. Thank you for -believing in me and my programming abilities (and other abilities) even when I -couldn't believe in myself! Very much appreciated especially coming from an -amazing programmer who I have huge admiration for! +I would like to thank my dear friend [Martijn +Schoemaker](https://www.ficture.nl) for encouraging me in my programming over +the years and who I owe a great deal to. Thank you for believing in me and my +programming abilities (and other abilities) even when I couldn't believe in +myself! Very much appreciated especially coming from an amazing programmer who I +have huge admiration for! I want to thank Ilya Kurdyukov for his helpful comments, suggestions and reporting the problem about half-width/full-width char spacing. He's been @@ -577,28 +571,35 @@ my entries. It's a huge honour; thank you! I also happen to **love** your comments as well as the award titles. And yes indeed 'most of us could use *[Double-layered Chocolate Fudge Cake][]*!' -[COMPILING]: COMPILING -[HACKING]: HACKING +If you wish to contact me please do so. Please contact via mastodon. You can try +email but I'm more likely to respond to mastodon messages. + +[COMPILING.md]: COMPILING.md +[COMPILING.html]: COMPILING.html +[HACKING.md]: HACKING.md +[HACKING.html]: HACKING.html [bugs.html]: bugs.html +[bugs.md]: bugs.md [troubleshooting.html]: troubleshooting.html [human snakes]: http://www.macroevolution.net/snake-human-hybrids.html +[chocolate-cake.md]: chocolate-cake.md [chocolate-cake.html]: chocolate-cake.html -[spoilers.markdown]: spoilers.markdown +[spoilers.md]: spoilers.md +[spoilers.html]: spoilers.md [Surround]: https://en.wikipedia.org/wiki/Surround_(video_game) [Snake walk: The physics of slithering]: https://www.bbc.co.uk/news/science-environment-35563941 [snake-colours.sh]: snake-colours.sh [gameplay.html]: gameplay.html +[gameplay.md]: gameplay.md [flying snakes]: https://www.bbc.co.uk/news/science-environment-25943693 [play.sh]: play.sh [great chocolate cake]: cake.jpg [https://ioccc.xexyl.net/2020/snake]: https://ioccc.xexyl.net/2020/snake [Double-layered Chocolate Fudge Cake]: chocolate-cake.html -[gameplay.html]: gameplay.html [terminals.html]: terminals.html +[terminals.md]: terminals.md [troubleshooting.html]: troubleshooting.html -[bugs.html]: bugs.html -[chocolate-cake.html]: chocolate-cake.html -[spoilers.html]: spoilers.html +[troubleshooting.md]: troubleshooting.md ## Copyright and CC BY-SA 4.0 License: diff --git a/2020/ferguson1/bugs.md b/2020/ferguson1/bugs.md index f700ba5e2..458c407a1 100644 --- a/2020/ferguson1/bugs.md +++ b/2020/ferguson1/bugs.md @@ -30,7 +30,9 @@ simply a fun consequence of the features I did implement. Let's say you want to verify that the evade mode is at the right count. How can you verify it without modifying the code? Try: - SIZE=0 SHED=1 SHEDS=1 EVADE=10 ./prog +```sh +SIZE=0 SHED=1 SHEDS=1 EVADE=10 ./prog +``` Since you start out at size 0 and you shed every movement then when you're size 10 (as long as you don't eat a bug of course!) the bug should evade. @@ -50,7 +52,9 @@ don't at this time remember any I might have done. One way to show this is in full is to set the initial size and growth size to a high value; then try each one individually. For example: - SIZE=100 ./prog +```sh +SIZE=100 ./prog +``` In this case after you make the first move the snake will keep growing and so the snake tail stays in the same spot until after it's the 'full size'. @@ -59,7 +63,7 @@ start to move too (i.e. if the tail isn't moving it is growing or else paused). In several tests I set the initial size to a high value, the max to a higher value still and enabled cannibalism and much of the screen was full of the snake -before it started to move. The [cannibalism.log][] has some examples of both +before it started to move. The [cannibalism.log.md][] has some examples of both cannibalism and a long snake that didn't move for most of the game. If however you let the snake get to the full size then eat a bug there can @@ -91,7 +95,7 @@ you can safely go back on yourself even without cannibalism enabled. This is intentional; a snake size of 0 is pointless but why should it not be playable anyway? -If SIZE < 0 you'll likely win straight away since it's unsigned and it'll wrap +If `SIZE < 0` you'll likely win straight away since it's unsigned and it'll wrap back to the maximum so you will win automatically (this is the same as the second mode the judges suggested with `SIZE=-1 ./prog`). @@ -111,37 +115,49 @@ way negative size will force a win. Here's a fun output: - < <<<+ +``` +< <<<+ +``` That's from: - SHED=1 SHEDS=-1 ./prog +```sh +SHED=1 SHEDS=-1 ./prog +``` And right after that you would see: - YOU WIN! - X:72/156 Y:20/41 S:997/997 B:0 +``` +YOU WIN! +X:72/156 Y:20/41 S:997/997 B:0 +``` Try this though: - SHEDS=-1 SHED=25 ./prog +```sh +SHEDS=-1 SHED=25 ./prog +``` And you'll see that you start to be the normal size but then you leave your head several places until you end up getting to the max size (by way of it being unsigned). This isn't a bug even if it might seem like one. In fact this is the basis of the grow/shrink mode of play that I talk about in the -[gameplay.md][] ([gameplay.html][]) file. +[gameplay.html][] ([gameplay.md][] on GitHub) file. Here's another thing to be aware of. Let's say you do: - SIZE=1 GROW=-1 ./prog +```sh +SIZE=1 GROW=-1 ./prog +``` How many bugs will it take before you win? In fact it's two: you would see the head twice: the second time once you 'shrink' down to size 0; it would then be that if you get another bug you will be at the 'max size': - YOU WIN! - X:81/156 Y:35/41 S:997/997 B:2 +```sh +YOU WIN! +X:81/156 Y:35/41 S:997/997 B:2 +``` # 'I was a few places behind my tail and I ran into it!' @@ -161,17 +177,21 @@ For instance it might look like this (the first line is as it happens, the second pointing to where it happens and the third being what's left after the rest of the snake has gone through). Doing `SHED=100 SHEDS=-1`: - ooooooooo>ooo> - ^ - > +``` +ooooooooo>ooo> + ^ + > +``` -The ^ points to the part that's split from the snake and which will be +The `^` points to the part that's split from the snake and which will be there on its own after the snake passes through it. Here's an example with it being `SHEDS=-3`: - It looks like the bug is in the snake -I show a different example in the [crazy.log][] file but what defines a coordinate +I show a different example in the [crazy.log.md][] file but what defines a coordinate which the snake occupies? If the snake breaks apart then the only part of the screen the snake is occupying is the place which is actually moving: if the snake decreases in size by 3 then the three respective characters you can go through safely. But this also means that a bug can go there! So you might see something like: - <*oooooooo +``` +<*oooooooo +``` This is because the snake is no longer there: in fact in this run the snake was quite a bit lower on the screen and 25 in length. @@ -214,35 +236,37 @@ the game is 10 x 10. This includes the walls and score line. Now the default max snake size is 997 but when the terminal is too small it adjusts the max snake size. For 10 lines and 10 columns you would see: - $ make test - terminal supports cursor movement - terminal supports making cursor invisible - terminal supports bold - terminal supports colours +```sh +$ make test +terminal supports cursor movement +terminal supports making cursor invisible +terminal supports bold +terminal supports colours - terminal rows 10 (7 playable) - terminal cols 10 (8 playable) +terminal rows 10 (7 playable) +terminal cols 10 (8 playable) - snake size: 49 (max size: 49) - bugs: 9 (max size: 9) +snake size: 49 (max size: 49) + bugs: 9 (max size: 9) - at least 28 columns recommended for snake size 49 (is 10) - at least 28 columns recommended for snake size 49 (is 10) +at least 28 columns recommended for snake size 49 (is 10) +at least 28 columns recommended for snake size 49 (is 10) - 1 problem detected (0 fatal). - make: *** [test] Error 1 +1 problem detected (0 fatal). +make: *** [test] Error 1 +``` First: what's the problem? It's just a warning that for the snake size of 49 the recommended size of columns is 28. However this is just for the score text; with only 10 columns it will overflow and wrap to the next line(s). But if you observe that 49 is the max snake size. How is this derived and why? -With 10 rows and columns it's calculated as 7 * 7 (i.e. it's +With 10 rows and columns it's calculated as `7 * 7` (i.e. it's `(cols-3)*(rows-3)`. However the number of playable locations is in this case 56 (`playable_rows * playable_columns`). I have played with this many times and I do not believe there should be a problem. If there is it's from a very poor implementation of rand() and I discuss this in -[troubleshooting.md][] ([troubleshooting.html][]). +[troubleshooting.html][] ([troubleshooting.md][] on GitHub). There I also give some test outputs without the cap in place to give an idea of when it became a problem (or would have). In short this is known but I do not @@ -277,7 +301,7 @@ had to say on it: However the function `mvaddch()` takes a `chtype` which amounts to a C char -with additional information and so the full width Ois too big for the +with additional information and so the full width `O`is too big for the function call. He reminded me of the old DOS box chars but even if this was easily duplicable (and it might be and I don't remember) the logic would have to be changed for drawing the snake and in such a way that would change @@ -294,12 +318,13 @@ suggested it is bugging me I once again here say it's not at all bugging me but it is very much appreciated and it means a great deal to me. Cheers.) -[crazy.log]: crazy.log +[crazy.log.md]: crazy.log.md [gameplay.md]: gameplay.md [troubleshooting.md]: troubleshooting.md [troubleshooting.html]: troubleshooting.html [gameplay.html]: gameplay.html -[cannibalism.log]: cannibalism.log +[gameplay.md]: gameplay.md +[cannibalism.log.md]: cannibalism.log.md [https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms]: https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms [spoilers]: spoilers.markdown [screenshot of halfwidth vs fullwidth]: halfwidth_vs_fullwidth.png diff --git a/2020/ferguson1/cannibalism.log b/2020/ferguson1/cannibalism.log.md similarity index 83% rename from 2020/ferguson1/cannibalism.log rename to 2020/ferguson1/cannibalism.log.md index 1ed07d196..58e179f7a 100644 --- a/2020/ferguson1/cannibalism.log +++ b/2020/ferguson1/cannibalism.log.md @@ -1,3 +1,26 @@ +# Extreme cannibalism in [2020 IOCCC 'Don't tread on me' Snake game](/2020/ferguson1/prog.c) + +To give an idea what cannibalism can look like (it's I believe a unique feature +to any other version of Snake), this file shows just how extreme cannibalism can +get with a long snake. I made a few changes, described below, to make it easier +to distinguish what is what. + +# Examples + +In the below game dumps I have replaced the bug with **`B`**, the head with +**`H`** and where it is known, the tail with **`T`**, in order to help +distinguish where they are. Since the head is replaced with **`H`** I have noted +the direction it was moving above each dump as well as at the right of the line; +each line with a bug, the head or tail is marked with upper case text at the +right to make it easier to find. + +The first run I include several dumps but there isn't much information about +most of them. + +## Example 0: snake moving right + + +``` X:45/89 Y:22/25 S:1675/2001 B:35 ########################################################################################## #oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo# @@ -7,7 +30,7 @@ X:45/89 Y:22/25 S:1675/2001 B:35 # o ooooooooooooooooooooooooo o o o o o # # o ooooooooooo ooooooooooooooooooooooo oooooooooooooooo o o o # #oooooooooooooooooooooooooooooooooooooooooooooooooooooo o o o o o o oo# -# o o ooooooooooooooooooooooooooooooooooooooo o o o*o o oooo o # +# o o ooooooooooooooooooooooooooooooooooooooo o o oBo o oooo o # <- *BUG* # o o o ooooooooooooooooooooooooooooooooooooooo o o o o o o # # o o o o o ooo o o oo oooooooooooooooooooooooo o # # o ooooooooooooooooo oooooooo o o oooooooooooo ooooooooooooooooooooooooo o # @@ -20,11 +43,15 @@ X:45/89 Y:22/25 S:1675/2001 B:35 # ooooooooooooooooooooooooooooooooooooooooooooooooooooooooo o o o o o # #oooooo o oooooo o o o o o o o ooooooooooooooooooooooooo o ooooooo# # o o o o o o oooo ooooooooooooooooo o o o o o # -# o o oo o o o ooooo> o oooooooo ooooo o # +# o o oo o o o oooooH o oooooooo ooooo o # <- *HEAD, RIGHT* #ooooooooo ooooooooooooooooooooo ooooooooooo ooooooo# #oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo# ########################################################################################## +``` +## Example 1: snake moving right + +``` X:79/89 Y:9/25 S:1680/2001 B:36 ########################################################################################## #oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo# @@ -34,13 +61,13 @@ X:79/89 Y:9/25 S:1680/2001 B:36 # o ooooooooooooooooooooooooo o o o o o # # o ooooooooooo ooooooooooooooooooooooo oooooooooooooooo o o o # #oooooooooooooooooooooooooooooooooooooooooooooooooooooo o o o o o o oo# -# o o oooooooooooooooooooooooo oo o o ooooooooooooooooooo> o # +# o o oooooooooooooooooooooooo oo o o oooooooooooooooooooH o # <- *HEAD, RIGHT* # o o o oooooooooooooooooooooooooooooooooooooooooo o o o o o # # o o o o o o o o o oo o oooooooooooooooooooooooo o # # o ooooooooooooooooo o o o o oooooooooooo ooooooooooooooooooooooooo o # # o o o o oooooo o o o o oooooooooooooooooooooooo o o o o o # #oooooooooooooooooo o o o oo o o o o o ooo oo o oo o o oooooooooooooooooooo# -# o oooooooooooooooooooooooooooooooooooooooooooooooooooo oo *o o oo o o o # +# o oooooooooooooooooooooooooooooooooooooooooooooooooooo oo Bo o oo o o o # <- *BUG* # o o ooooooooooooooooooooooooooooooooooooooooooooooooo o oo o o o # #oooooooooo oooo o o o o o o o ooo o oooooooooooooooooo ooooooooooooooooo# # oooooooooooooooo o o ooooooooo o ooo o o o o o o ooooooooooooo # @@ -51,7 +78,11 @@ X:79/89 Y:9/25 S:1680/2001 B:36 #ooooooooo ooooooooooooooooooooo ooooooooooo ooooooo# #oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo# ########################################################################################## +``` +## Example 2: snake moving left + +``` X:53/89 Y:18/25 S:1690/2001 B:38 ########################################################################################## #oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo# @@ -61,7 +92,7 @@ X:53/89 Y:18/25 S:1690/2001 B:38 # o ooooooooooooooooooooooooo o o o o o # # o ooooooooooo ooooooooooooooooo o oooooooooooooooo o o o # #oooooooooooooooooooooooooooooooooooooooooooooooooooooo o o o o o o oo# -# o * o oooooooooooooooooooooooo o o o oooooooooooooooooooo o # +# o B o oooooooooooooooooooooooo o o o oooooooooooooooooooo o # <- *BUG* # o o o oooooooooooooooooooooooooooooooooooooooooo o o o o o o # # o o o o o o o o o o o oooooooooooooooooooooooo o o # # o ooooooooooooooooo o o o o oooooooooo o ooooooooooooooooooooooooo o # @@ -70,7 +101,7 @@ X:53/89 Y:18/25 S:1690/2001 B:38 # o oooooooooooooooooooooooooooooooooooooooooooooooooooo oo oo o oo o o o # # o o ooooooooooooooooooooooooooooooooooooooooooooooooo o oo o o o # #oooooooooo oooo o o o o o o o o o o ooooooooooooooooo ooooooooooooooooo# -# oooooooooooooooo o o ooooooooo o o o o +![picture of the Double-layered chocolate fudge cake](cake.jpg) There are two sets of ingredients and instructions; the cake and the icing. In addition there are some notes to pay attention to; some will be repeated because @@ -57,8 +57,12 @@ recipe notes because they're really important!** **PAY CLOSE ATTENTION TO THESE:** -* **USE MARGARINE**. Butter does not work well. If you think it will come out - better by using butter you're very mistaken; it will come out badly! +* **USE MARGARINE, _NOT_ BUTTER!** Butter does not work well. If you think it + will come out better by using butter you're very mistaken; it will come out + badly! People have come back saying it didn't come out well and they are + asked if they used butter or margarine. They had used butter because they + 'know better' but they were very wrong; they did not know better and the + cake was awful because of this. * Over the years they changed the size of the unsweetened chocolate squares; they used to be one ounce each now they are 1/4 ounce each square so be sure to @@ -71,13 +75,13 @@ recipe notes because they're really important!** to fully cool on racks. The important point is that they don't overcook. * When the recipe was first written they sold powdered sugar in a box; now - it's confectioners sugar in a bag. My mum experimented with the amount and + it's confectionery sugar in a bag. My mum experimented with the amount and found that 4 cups seems about right. * She uses **WHOLE MILK** for this recipe; she doesn't know if it really matters but given that she and I both prefer skim milk except for here and in chocolate milk I would recommend whole milk for this recipe too. In any case - it turns out great **if you follow *everything* to a T!** + it turns out great **IF YOU FOLLOW *EVERYTHING* TO A T!** * Use only **PURE VANILLA EXTRACT**! Do **NOT USE imitation vanilla!** @@ -98,37 +102,37 @@ recipe notes because they're really important!** ## Cake Preparation -1. Lightly grease two 9 x 1.5 inch round pans; lightly dust with flour. +1. Lightly grease **TWO 9 X 1.5 INCH ROUND PANS**; lightly dust with flour. -2. Preheat oven to 350 F (176.67 C). +2. Preheat oven to **350 F (176.67 C)**. ## Cake Directions -1. Melt **3 oz unsweetened chocolate** in double boiler or small bowl over - **hot (*but not boiling*) water**; let cool whilst proceeding. +1. Melt **3 OZ UNSWEETENED CHOCOLATE** in double boiler or small bowl over + **hot (*BUT NOT BOILING*) water**; let cool whilst proceeding. -2. Sift **2 1/4 cups flour**, **2 tsp baking soda**, and **1/2 tsp salt** +2. Sift **2 1/4 CUPS FLOUR**, **2 TSP BAKING SODA**, and **1/2 TSP SALT** -3. Beat **1 stick margarine** in large bowl *until soft*. +3. Beat **1 STICK MARGARINE** in large bowl *until soft*. Again **MARGARINE**. -4. Add **2 1/4 cups packed brown sugar** and **3 eggs**. Beat until light and +4. Add **2 1/4 CUPS PACKED BROWN SUGAR** and **3 EGGS**. Beat until light and fluffy. -5. Beat in **1 1/2 tsp vanilla** and **cooled melted chocolate**. +5. Beat in **1 1/2 TSP VANILLA** and **COOLED MELTED CHOCOLATE**. -6. Stir in dry ingredients alternately with **1 cup sour cream**; always beat +6. Stir in dry ingredients alternately with **1 CUP SOUR CREAM**; always beat until smooth. -7. Stir in **1 cup boiling water**. +7. Stir in **1 CUP _BOILING_ WATER**. 8. Pour into prepared pans. -9. Bake for **ONLY 35 minutes** (NO LONGER) at 350 F (176.67 C). +9. Bake for **ONLY 35 MINUTES** (**NO LONGER!**) at **350 F (176.67 C)**. 10. When you take the cake out put the cake pans on a cooling rack for **TWO - MINUTES ONLY AND THEN IMMEDIATELY TURN CAKES OUT ON TO RACK**. Let cool - completely. + MINUTES _ONLY_ AND _THEN IMMEDIATELY TURN CAKES OUT_ ON TO RACK**. Let **COOL + _COMPLETELY_**. ## Icing Ingredients @@ -146,33 +150,33 @@ bowl can sit in. **PAY CLOSE ATTENTION TO THESE:** -* Make sure that the melted chocolate and margarine does not get solid. +* **Make sure** that the melted chocolate and margarine does not get solid. -* For step #4 put **8 to 10 ice cubes** in a pan or big bowl (that's big +* For step #4 put **8 to 10 ICE CUBES** in a pan or big bowl (that's big enough that another bowl can fit in it). Add an inch of water and then set - the bowl with the icing in the pan or bowl of ice water. **Do not let the - icing get wet!** + the bowl with the icing in the pan or bowl of ice water. **DO NOT LET THE + ICING GET WET!** -* Do not let icing get too thick. +* **DO NOT LET ICING GET TOO THICK.** -* Use **whole milk.** +* Use **WHOLE MILK.** -* Use only **pure vanilla extract**! Do **not use imitation vanilla!** +* Use **ONLY PURE VANILLA EXTRACT**! **DO NOT USE IMITATION VANILLA!** ## Icing Directions -1. Combine **4 oz unsweetened chocolate** and **1/2 cup margarine** in pan. +1. Combine **4 OZ UNSWEETENED CHOCOLATE** and **1/2 CUP MARGARINE** in pan. Melt and remove from heat. **DO NOT LET IT GET SOLID.** -2. Combine **3 1/4 cups powdered sugar**, **1/2 cups whole milk** and **2 tsp - vanilla** into a bowl. **Stir until smooth**. +2. Combine **3 1/4 CUPS POWDERED SUGAR**, **1/2 CUPS WHOLE MILK** and **2 TSP + VANILLA** into a bowl. **STIR UNTIL SMOOTH**. 3. Add chocolate mixture. 4. Set bowl in pan/bowl of ice and water. Beat with spoon/mixer until it's - thick BUT not too thick. Make sure icing doesn't get wet! The idea is to + thick BUT not too thick. **Make _SURE_ ICING DOES _NOT_ GET WET!** The idea is to **MAKE THE BOWL IT'S IN COLD *but not let the icing get wet***. [picture]: cake.jpg diff --git a/2020/ferguson1/crazy.log b/2020/ferguson1/crazy.log.md similarity index 89% rename from 2020/ferguson1/crazy.log rename to 2020/ferguson1/crazy.log.md index d23e96418..eb88e46cf 100644 --- a/2020/ferguson1/crazy.log +++ b/2020/ferguson1/crazy.log.md @@ -1,6 +1,8 @@ The following are a few screen dumps of: - SIZE=100 SHEDS=5 GROW=-10 SHED=50 MAXSIZE=250 ./prog +```sh +SIZE=100 SHEDS=5 GROW=-10 SHED=50 MAXSIZE=250 ./prog +``` As you will see it took 17 bugs to get down to below 0. Notice how I had to get down to 0 more than once: because I moved enough times before I got the last @@ -8,12 +10,15 @@ bug that I grew by 5 in size. I then however moved a bit more and ate a bug which brought me down to -5 therefore winning at the max size of 250. This then showed: - YOU WIN! - X:62/89 Y:5/25 S:250/250 B:17 +``` +YOU WIN! +X:62/89 Y:5/25 S:250/250 B:17 +``` Observe all the arrows on the screen; that's where a bug was that I ate and -then I split off losing 10 in size. The first one dump I got myself already to 15: +then I split off losing 10 in size. The first dump I'm already at 15/250: +``` X:17/89 Y:15/25 S:15/250 B:13 ########################################################################################## # # # oooooo # ########################################################################################## +``` -But here now I'm at 0; the head is the sole left arrows: +But here now I'm at 0; the head is marked `H` and it's moving left. +``` X:19/89 Y:12/25 S:0/250 B:16 ########################################################################################## # # # o o # @@ -69,16 +76,21 @@ X:19/89 Y:12/25 S:0/250 B:16 # o o> # # oooooo # ########################################################################################## +``` -I ended up moving enough times where my size went back up to 5; the head of the -snake is in this file line 80 col 56; the bug is at line 81 col 63: +I ended up moving enough times where my size went back up to 5. +Below the snake is moving right and its head is indicated by a `H` with the line +marked at the right; the bug is marked as `B` and is also marked at the right. +Notice how it's in the body of the snake (but see below)! + +``` X:55/89 Y:4/25 S:5/250 B:16 ########################################################################################## # oo # -# oooo> oooo # -# o o oooooo*oo> v # +# ooooH oooo # <- *HEAD, RIGHT* +# o o ooooooBoo> v # <- *BUG* # o o oo o oo> # # o o o o oo # # o o o oooo # @@ -99,6 +111,7 @@ X:55/89 Y:4/25 S:5/250 B:16 # o o> # # oooooo # ########################################################################################## +``` But did you see anything strange? The bug is on the fourth line below the upper wall. However it appears to be inside the body of the snake! But actually that's just where diff --git a/2020/ferguson1/gameplay.md b/2020/ferguson1/gameplay.md index 63025311b..1e25f9fcf 100644 --- a/2020/ferguson1/gameplay.md +++ b/2020/ferguson1/gameplay.md @@ -69,20 +69,21 @@ for the input keys. # 1. Testing terminal environment/capabilities Most people probably won't have any issue at all but for those who have any -problems with the terminal see the [terminals.md][] file for more -information on the terminal capabilities testing utility I include. +problems with the terminal see the [terminals.html][] ([terminals.md][] on +GitHub) file for more information on the terminal capabilities testing utility I +include. -For troubleshooting other problems see [troubleshooting.md][] -([troubleshooting.html][]) and [bugs.md][] ([bugs.html][]). +For troubleshooting other problems see [troubleshooting.html][] +([troubleshooting.md][] on GitHub) and [bugs.html][] ([bugs.md][] on GitHub). # 2. Input keys -- Left, right, up and down **arrow keys**: Move that direction. +- Left, right, up and down **arrow keys**: move that direction. -- 'q' (and 'Q'): Quit the game. +- `q` (and `Q`): quit the game. -- Space (`' '`): Pause/resume the game (direction keys will also resume). +- Space: pause/resume the game (direction keys will also resume). Note that no other keys will resume the game; however if you press a key that `getch()` picks up on and the game is not paused then it will be as if you pressed the current direction key (assuming you already moved the snake). @@ -106,24 +107,26 @@ below. Note that the top line is the score/status line: the top wall is at line (ncurses is the opposite: Y/X). I will parenthesise the numbers below to refer to the number in the diagram: - X:24/49 Y:8/16 S:5/658 B:0 - ################################################## - # # - # # - # # - # # - # # - # # - # + # - # # - # * # - # # - # # - # # - # # - # # - ################################################## +``` +X:24/49 Y:8/16 S:5/658 B:0 +################################################## +# # +# # +# # +# # +# # +# # +# + # +# # +# * # +# # +# # +# # +# # +# # +################################################## +``` - The snake (`+`) is at (24),(8). The bug char is `*` and the wall char is `#`. When the snake moves the head will be an arrow facing the direction it @@ -149,66 +152,72 @@ to the number in the diagram: ## Gameplay: Playing the game - X:39/49 Y:8/16 S:5/658 B:0 - ################################################## - # # - # # - # # - # # - # # - # # - # oooo> # - # # - # * # - # # - # # - # # - # # - # # - ################################################## +``` +X:39/49 Y:8/16 S:5/658 B:0 +################################################## +# # +# # +# # +# # +# # +# # +# oooo> # +# # +# * # +# # +# # +# # +# # +# # +################################################## +``` I let the snake grow to its full size (with the head at (39),(8)) and I'm two places above the bug so let's go down: - X:39/49 Y:9/16 S:5/658 B:0 - ################################################## - # # - # # - # # - # # - # # - # # - # oooo # - # v # - # * # - # # - # # - # # - # # - # # - ################################################## +``` +X:39/49 Y:9/16 S:5/658 B:0 +################################################## +# # +# # +# # +# # +# # +# # +# oooo # +# v # +# * # +# # +# # +# # +# # +# # +################################################## +``` Now you see that the snake is going down and in one move the bug will be eaten. Let's do that: - X:36/49 Y:10/16 S:10/658 B:1 - ################################################## - # # - # # - # # - # * # - # # - # # - # # - # # - # ^ o # - # oooo # - # # - # # - # # - # # - ################################################## +``` +X:36/49 Y:10/16 S:10/658 B:1 +################################################## +# # +# # +# # +# * # +# # +# # +# # +# # +# ^ o # +# oooo # +# # +# # +# # +# # +################################################## +``` Observe that the bug was eaten and a new bug spawned elsewhere. I went left three and then up one and could slither on to the bug. @@ -220,44 +229,48 @@ By default walls are passable (**WALLS=1**). Let's get to full size and go through the top wall: - X:36/49 Y:15/16 S:10/658 B:1 - ################################################## - # o # - # o # - # o # - # * o # - # o # - # o # - # o # - # o # - # o # - # # - # # - # # - # # - # ^ # - ################################################## +``` +X:36/49 Y:15/16 S:10/658 B:1 +################################################## +# o # +# o # +# o # +# * o # +# o # +# o # +# o # +# o # +# o # +# # +# # +# # +# # +# ^ # +################################################## +``` There you can see I have grown to the full size and went through the top wall; the head is now at the opposite wall. Continuing: - X:36/49 Y:11/16 S:10/658 B:1 - ################################################## - # o # - # o # - # o # - # * o # - # o # - # # - # # - # # - # # - # ^ # - # o # - # o # - # o # - # o # - ################################################## +``` +X:36/49 Y:11/16 S:10/658 B:1 +################################################## +# o # +# o # +# o # +# * o # +# o # +# # +# # +# # +# # +# ^ # +# o # +# o # +# o # +# o # +################################################## +``` I might then have turned to the left and then shortly go up to get the bug. This goes on until you lose, quit or win the game. @@ -266,30 +279,32 @@ goes on until you lose, quit or win the game. When you specify **WALLS=0** the walls become an obstacle that end the game. It might look like (I set the starting size to 150 and had only just started): - - X:20/49 Y:2/16 S:150/658 B:0 - ################################################## - # ^ # - # o # - # o * # - # o # - # o # - # o # - # ooooo # - # # - # # - # # - # # - # # - # # - # # - ################################################## +``` +X:20/49 Y:2/16 S:150/658 B:0 +################################################## +# ^ # +# o # +# o * # +# o # +# o # +# o # +# ooooo # +# # +# # +# # +# # +# # +# # +# # +################################################## +``` If I continue going up I will see: - OUCH! - X:20/49 Y:1/16 S:150/658 B:0 - +``` +OUCH! +X:20/49 Y:1/16 S:150/658 B:0 +``` @@ -298,129 +313,134 @@ If I continue going up I will see: By default cannibalism is disabled (**CANNIBAL=0**) so if you run into yourself it might look something like: - X:45/49 Y:10/16 S:10/658 B:1 - ################################################## - # # - # # - # # - # * # - # # - # # - # # - # ooooo # - # ^ o # - # ooo # - # # - # # - # # - # # - ################################################## +``` +X:45/49 Y:10/16 S:10/658 B:1 +################################################## +# # +# # +# # +# * # +# # +# # +# # +# ooooo # +# ^ o # +# ooo # +# # +# # +# # +# # +################################################## +``` If I were to do any movement but turn to the left I would run into myself. I'll go to the right two spaces: - OW! - X:47/49 Y:10/16 S:10/658 B:1 - +``` +OW! +X:47/49 Y:10/16 S:10/658 B:1 +``` But **CANNIBAL=1** can look very funny both in movement and still especially when you go through yourself several times when the snake is rather long. For example going through walls and the snake a few times: - X:4/49 Y:12/16 S:165/658 B:3 - ################################################## - #oo o ooooo o o o# - # oooo o ooo o# - # ooooooooooooooooooo# - # o # - # oooooooooo o # - # o o o # - # o oooo o o # - # o o o o # - # ooooooooooooooo # - # o o* # - # oo> o o # - # o oooooooo o # - #oooooooooooooo o oooo oooooooo# - # o o o o o # - ################################################## +``` +X:4/49 Y:12/16 S:165/658 B:3 +################################################## +#oo o ooooo o o o# +# oooo o ooo o# +# ooooooooooooooooooo# +# o # +# oooooooooo o # +# o o o # +# o oooo o o # +# o o o o # +# ooooooooooooooo # +# o o* # +# oo> o o # +# o oooooooo o # +#oooooooooooooo o oooo oooooooo# +# o o o o o # +################################################## +``` I'll go back through myself now: - X:6/49 Y:14/16 S:165/658 B:3 - ################################################## - #oo o ooooo o o o# - # oooo o ooo o# - # ooooooooooooooooooo# - # o # - # oooooooooo o # - # o o o # - # o oooo o o # - # o o o o # - # ooooooooooooooo # - # o o* # - # ooo o o # - # oo oooooooo o # - #ooooo>oooooooo o oooo oooooooo# - # o o o o o # - ################################################## +``` +X:6/49 Y:14/16 S:165/658 B:3 +################################################## +#oo o ooooo o o o# +# oooo o ooo o# +# ooooooooooooooooooo# +# o # +# oooooooooo o # +# o o o # +# o oooo o o # +# o o o o # +# ooooooooooooooo # +# o o* # +# ooo o o # +# oo oooooooo o # +#ooooo>oooooooo o oooo oooooooo# +# o o o o o # +################################################## +``` If you note that the head is at (6),(14) I will go one more to the right and you will see that the arrow has moved over: - X:7/49 Y:14/16 S:165/658 B:3 - ################################################## - #oo o ooooo o o o# - # oooo o ooo o# - # ooooooooooooooooooo# - # o # - # oooooooooo o # - # o o o # - # o oooo o o # - # o o o o # - # ooooooooooooooo # - # o o* # - # ooo o o # - # oo oooooooo o # - #oooooo>ooooooo o oooo oooooooo# - # o o o o o # - ################################################## +``` +X:7/49 Y:14/16 S:165/658 B:3 +################################################## +#oo o ooooo o o o# +# oooo o ooo o# +# ooooooooooooooooooo# +# o # +# oooooooooo o # +# o o o # +# o oooo o o # +# o o o o # +# ooooooooooooooo # +# o o* # +# ooo o o # +# oo oooooooo o # +#oooooo>ooooooo o oooo oooooooo# +# o o o o o # +################################################## +``` -Try this: Get a reasonable length and then go back on yourself (if you're going +Try this: get a reasonable length and then go back on yourself (if you're going left go right etc.) and then after some length (but before you get beyond the snake) turn (so that you go perpendicular) and then watch as the snake starts unwinding at one place and then suddenly unwinds another direction. -An example of extreme cannibalism is in the [cannibalism.log][] file. It has -more than one run the first of one has several dumps. I didn't move for a long -time: the initial size was 1500 and I would have won before moving if I went -after bugs right away. In the last two captures of the first invocation (the -third and second to last dump) the bug, head and tail of the snake are at: - - Bug: line 87, col 47 - Head: line 88, col 62; and line 115, col 48 - Tail: line 84, col 46; and line 112, col 29 - -The final example has the snake inside itself. +An example of extreme cannibalism is in the [cannibalism.log.html][] +([cannibalism.log.md][] on GitHub) file. It explains information about the file +including how to find the bug, head and tail of the snake, at least where it was +documented. The first run has several dumps. The final example has the snake +inside itself. # Gameplay: Shedding (stretching) -This feature will make you grow by the value of **SHEDS** for every **SHED** +This feature will make you grow by the value of **`SHEDS`** for every **`SHED`** movements (the counter isn't incremented when you eat a bug). Basically growing without eating a bug (stretching would be better name here). # Gameplay: Winning -If you ever get to the **MAXSIZE** the game is won. You can force a win by +If you ever get to the **`MAXSIZE`** the game is won. You can force a win by setting the max size to a smaller value than the size you specify (or the default) or setting the size to higher than the default (or < 0 which will end up being > the max size though I suppose there might be some value that makes it less than again - I'm not going to try and figure that out however). Anyway: - SIZE=-1 ./prog - YOU WIN! - X:24/49 Y:8/16 S:658/658 B:0 +```sh +SIZE=-1 ./prog +YOU WIN! +X:24/49 Y:8/16 S:658/658 B:0 +``` Observe that the size isn't the default 997: because the screen size is too small for that value (see [terminals.md][]). @@ -429,7 +449,8 @@ The reason I chose 997 is that it leaves a bit of a challenge for some (maybe most) people but it's still winnable. Previously even I couldn't have won unless maybe a much bigger screen, if both cheat modes were disabled. I probably could win without any cheat mode enabled on my 24" monitor but I probably would need -at least one cheat mode on my 13" laptop (I don't need both enabled). +at least one cheat mode on my 16" laptop (I don't need both enabled). I don't +think I need either for 997. The beauty though is the game can be winnable by anyone since you can define the max size to win. Games are meant to be fun: who enjoys games that can never be @@ -449,14 +470,16 @@ the game is won is 199 - also a prime! If you wish to quit you can hit 'q' (case-insensitive). For example: - X:24/49 Y:8/16 S:5/658 B:0 +``` +X:24/49 Y:8/16 S:5/658 B:0 +``` # 4. Gameplay modes -Here I list a number of different modes of play. In the [bugs.md][] -([bugs.html][]) file I even show how there's a built-in test unit for some +Here I list a number of different modes of play. In the [bugs.html][] +([bugs.md][] on GitHub) file I even show how there's a built-in test unit for some modes! There are certainly other modes that could be imagined: the modes below happened over time and some were simply an accidental discovery or something I thought of by a chance; others were thought out from the beginning but were @@ -469,7 +492,7 @@ the modes below. ## Photosensitive epilepsy/Stimulation overload trigger warnings If you have **photosensitive epilepsy please be careful** especially with low values -for both **WAIT** and **EVADE**. It appears that the [number of hertz (flashes) +for both **`WAIT`** and **`EVADE`**. It appears that the [number of hertz (flashes) per second triggering seizures][] is wide but depending on the variables it easily can be in the range. @@ -486,19 +509,25 @@ If you want to draw the snake wherever you like on the screen you can do this by modifying the wait time (for input) to -1 (or any value < 0): then the snake does not move until you press a movement key. For example: - WAIT=-1 ./prog +```sh +WAIT=-1 ./prog +``` When you eat a bug the snake will grow and you can draw more. If you want to make it so you can go through yourself: - WAIT=-1 CANNIBAL=1 ./prog +```sh +WAIT=-1 CANNIBAL=1 ./prog +``` If you don't want to start out so small (i.e. you want to be able to draw more quickly) you can just set the size to a bigger number (and you could do the same with growth and moult/shed): - SIZE=50 CANNIBAL=1 WAIT=-1 ./prog +```sh +SIZE=50 CANNIBAL=1 WAIT=-1 ./prog +``` Do note that although you're a bigger size you still grow one movement at a time. @@ -506,12 +535,16 @@ time. Okay but then if you get too many bugs the drawing will be over. If this proves to be a problem simply do: - SIZE=100 CANNIBAL=1 WAIT=-1 GROW=0 ./prog +```sh +SIZE=100 CANNIBAL=1 WAIT=-1 GROW=0 ./prog +``` Or something like that (maybe make the size bigger but that's up to you). You could also set the max size to be the highest possible by saying - MAXSIZE=-1 +```sh +MAXSIZE=-1 +``` Which I've done in the [play.sh][] script. @@ -522,11 +555,14 @@ perfect: the snake after all does not leave gaps and the game does not support diagonal movement and I also made a mistake and had to modify what I was aiming for. But you can consider this mode drawing or practice mode. - oooooooooo ooooo o oo ooooo - o o oo o oo o ooo o - oooo o oo ooooooo oooo ooooo - o o ooo oo o ooo o - oooo o oo ooo oooooooo> + + + oooooooooo ooooo o oo ooooo + o o oo o oo o ooo o + oooo o oo ooooooo oooo ooooo + o o ooo oo o ooo o + oooo o oo ooo oooooooo> + ## Gameplay mode: Computer playing / Automatic mode (Photosensitive epilepsy/Stimulation overload trigger) @@ -542,7 +578,9 @@ too. If you're still here you can create this effect like: - WAIT=0 WALLS=1 CANNIBAL=1 ./prog +```sh +WAIT=0 WALLS=1 CANNIBAL=1 ./prog +``` As long as the bug evades you'll find that the snake is growing because it's actually eating bugs; the computer is actually playing the game by itself! You @@ -566,14 +604,18 @@ so with fewer available it has a harder time finding a place in that one line. Here's how to make the bug move every time the snake moves: - CANNIBAL=1 WALLS=1 WAIT=0 EVADE=1 ./prog +```sh +CANNIBAL=1 WALLS=1 WAIT=0 EVADE=1 ./prog +``` #### Help the computer win fairly quickly If you want to see the game 'win' try something like: - CANNIBAL=1 WALLS=1 WAIT=0 EVADE=1 MAXSIZE=10 ./prog +```sh +CANNIBAL=1 WALLS=1 WAIT=0 EVADE=1 MAXSIZE=10 ./prog +``` #### Negative growth (Shrink) Automatic mode @@ -581,7 +623,9 @@ If you want to see the game 'win' try something like: Here's a fun one I just thought of (a long time after these other modes were thought of): - WAIT=0 EVADE=1 GROW=-1 SIZE=9 MAXSIZE=10 CANNIBAL=1 ./prog +```sh +WAIT=0 EVADE=1 GROW=-1 SIZE=9 MAXSIZE=10 CANNIBAL=1 ./prog +``` What you'll see is that first the snake will get to the size of 9 - whether it shows to be 10 characters depends on whether or not it gets a bug before it can @@ -594,7 +638,9 @@ then the head again (i.e. 1 then 0 in size) and then win! This is also in the Of course you can also do something like: - WAIT=5 WALLS=1 CANNIBAL=1 ./prog +```sh +WAIT=5 WALLS=1 CANNIBAL=1 ./prog +``` Which although might not seem like it is significantly slower. @@ -611,13 +657,17 @@ of success in catching bugs? Obviously the dimensions will affect this value. How long will it take for the snake to run into itself? For instance by doing: - WAIT=0 ./prog +```sh +WAIT=0 ./prog +``` -On my 13" MacBook Pro at the default settings going horizontally the snake ran -into itself at: +On my 13" MacBook Pro (replaced later by a 16") at the default settings going +horizontally the snake ran into itself at: - OW! - X:57/156 Y:20/41 S:155/997 B:30 +``` +OW! +X:57/156 Y:20/41 S:155/997 B:30 +``` What if you set the size to a high value? The lowest? There are bound to be other games to play with this feature! @@ -632,7 +682,9 @@ You have a negative shedding growth and a positive growth size: negative and positive winning. Depending on the parameters specified it might go one way over the other. Try: - SIZE=150 SHEDS=-5 GROW=10 SHED=50 MAXSIZE=250 ./prog +```sh +SIZE=150 SHEDS=-5 GROW=10 SHED=50 MAXSIZE=250 ./prog +``` What this does is set the size to 150 (to make it not go down so quickly) and then for each bug you eat it adds 5 to the size; for every 50 moves (that you @@ -646,13 +698,16 @@ The parameters above were chosen after playing with the mode a bit to find a value that wouldn't take that much time but still would pose a challenge. One could reverse it so that one shrinks more than growing. -The [crazy.log][] file has several screen dumps with this idea. +The [crazy.log.html][] ([crazy.log.md][] on GitHub) file has several screen +dumps with this idea. You could also have it so that eating a bug makes you shrink and moving so many moves you grow. I tried this and for me it was far more fun. The [play.sh][] also has this mode: - SIZE=100 SHEDS=5 GROW=-10 SHED=50 MAXSIZE=250 ./prog +```sh +SIZE=100 SHEDS=5 GROW=-10 SHED=50 MAXSIZE=250 ./prog +``` Obviously there are many other variations. The [play.sh][] script has some of them (the above is option 5; others are 4, 15 and 16 but only options 4 and 5 @@ -672,7 +727,9 @@ snake moving too. Anyway this might sound absurd but it can be somewhat hypnotic by doing: - EVADE=1 CANNIBAL=1 ./prog +```sh +EVADE=1 CANNIBAL=1 ./prog +``` And just moving the snake about not trying to catch any bugs - just let whatever happens happen. @@ -686,7 +743,9 @@ the growth size to 0 and then just move the snake round and round eating bugs until you want to quit. You can enable cannibalism so that you don't have to worry about even running into yourself and losing: - GROW=0 CANNIBAL=1 ./prog +```sh +GROW=0 CANNIBAL=1 ./prog +``` ## Gameplay mode: Expansibility @@ -715,11 +774,15 @@ this file discusses as well as allowing to easily change the colours. To do this use the [snake-colours][] script like so: - ./snake-colours +```sh +./snake-colours +``` If you want to pass in specific variables you can do that too e.g.: - CANNIBAL=1 ./snake-colours +```sh +CANNIBAL=1 ./snake-colours +``` The script will prompt you for the colour of the walls, snake head, body and the bug. @@ -736,11 +799,15 @@ you choose uses then the script will override what you pass in. To use you can do something like: - ./play.sh +```sh +./play.sh +``` Or to make it so walls are an obstacle: - WALLS=0 ./play.sh +```sh +WALLS=0 ./play.sh +``` # 6. Notes about some of the game variables @@ -757,7 +824,7 @@ snake to move slower you have to increase the wait time! ## EVADE: Bug evasion frequency -For every **EVADE** snake movements the bug will try and find a new place to +For every **`EVADE`** snake movements the bug will try and find a new place to occupy. It might be very close to it and I do not ensure it's a new place at all. @@ -810,12 +877,15 @@ years ago but I know it's true now. **Believe in yourself. Always.** [troubleshooting.html]: troubleshooting.html [bugs.md]: bugs.md [bugs.html]: bugs.html -[spoilers.markdown]: spoilers.markdown +[spoilers.md]: spoilers.md +[spoilers.html]: spoilers.html [snake-colours]: snake-colours [number of hertz (flashes) per second triggering seizures]: https://www.epilepsysociety.org.uk/photosensitive-epilepsy#.Xjgpwi2ZOgQ [termcaps.c]: termcaps.c -[cannibalism.log]: cannibalism.log -[crazy.log]: crazy.log +[cannibalism.log.md]: cannibalism.log.md +[cannibalism.log.html]: cannibalism.log.html +[crazy.log.md]: crazy.log.md +[crazy.log.md]: crazy.log.html [play.sh]: play.sh ----------------------------------------------------------------------------------------------------- diff --git a/2020/ferguson1/play.sh b/2020/ferguson1/play.sh index ab3602f01..56914d47d 100755 --- a/2020/ferguson1/play.sh +++ b/2020/ferguson1/play.sh @@ -35,7 +35,8 @@ # (added 16 August 2020). This will start you at 400 and every 100 movements you # would lose 5 in length; when you eat a bug you would grow by 5 (default). # -# Last updated: 16 August 2020 +# Last updated: 15 April 2023 +# COLOUR[0]="BLACK" COLOUR[1]="RED" COLOUR[2]="GREEN" @@ -84,7 +85,7 @@ function configure_colours() for i in "WALL" "WALL (BACKGROUND)" "HEAD" "HEAD (BACKGROUND)" "BODY" "BODY (BACKGROUND)" "BUG" "BUG (BACKGROUND)"; do show_colours "${i}" x="${?}" - if [ "${x}" != 255 ]; then + if [[ "${x}" != 255 ]]; then COLOURS[$j]="${COLOURS[$j]}${COLOUR[$x]}" else COLOURS[$j]=${DFLT[$j]} @@ -92,24 +93,34 @@ function configure_colours() j=$j+1 done - echo cc -o prog.alt prog.alt.c -D'f(a,b)'='((a)<(b)?(a):(b))' ${COLOURS[0]} ${COLOURS[1]} \ - ${COLOURS[2]} ${COLOURS[3]} ${COLOURS[4]} ${COLOURS[5]} ${COLOURS[6]} ${COLOURS[7]} -lncurses + echo cc -o prog.alt prog.alt.c -D'f(a,b)'='((a)<(b)?(a):(b))' "${COLOURS[0]}" "${COLOURS[1]}" \ + "${COLOURS[2]}" "${COLOURS[3]}" "${COLOURS[4]}" "${COLOURS[5]}" "${COLOURS[6]}" "${COLOURS[7]}" -lncurses - cc -o prog.alt prog.alt.c -D'f(a,b)'='((a)<(b)?(a):(b))' ${COLOURS[0]} ${COLOURS[1]} \ - ${COLOURS[2]} ${COLOURS[3]} ${COLOURS[4]} ${COLOURS[5]} ${COLOURS[6]} ${COLOURS[7]} -lncurses || exit 1 + cc -o prog.alt prog.alt.c -D'f(a,b)'='((a)<(b)?(a):(b))' "${COLOURS[0]}" "${COLOURS[1]}" \ + "${COLOURS[2]}" "${COLOURS[3]}" "${COLOURS[4]}" "${COLOURS[5]}" "${COLOURS[6]}" "${COLOURS[7]}" -lncurses || exit 1 + +} +function just_compile() +{ + echo cc -o prog.alt prog.alt.c -D'f(a,b)'='((a)<(b)?(a):(b))' "${DFLT[0]}" "${DFLT[1]}" \ + "${DFLT[2]}" "${DFLT[3]}" "${DFLT[4]}" "${DFLT[5]}" "${DFLT[6]}" "${DFLT[7]}" -lncurses + + cc -o prog.alt prog.alt.c -D'f(a,b)'='((a)<(b)?(a):(b))' "${DFLT[0]}" "${DFLT[1]}" \ + "${DFLT[2]}" "${DFLT[3]}" "${DFLT[4]}" "${DFLT[5]}" "${DFLT[6]}" "${DFLT[7]}" -lncurses || exit 1 } function testcaps() { make || exit 1 ./termcaps T="${?}" - if [ "${T}" -ne 0 ]; then + if [[ "${T}" -ne 0 ]]; then read -rp "Terminal issues detected; do you wish to continue anyway (Y/N) ? " ans [[ "${ans}" != "y" ]] && [[ "${ans}" != "Y" ]] && exit 1 fi } function menu() { + echo printf "** GAME MODE SELECTION MENU **\n\n" echo "(0) Drawing mode" @@ -211,66 +222,75 @@ function play() configure_colours ;; *) + just_compile ;; esac - menu - read -rp "Make your selection (0 - 7 or any other key to exit): " mode - case "${mode}" in - 0) # Drawing mode 0 - draw0 - ;; - 1) # Drawing mode 1 - draw1 - ;; - 2) # Automatic mode (computer plays by itself) (photosensitive epilepsy/stimulation overload trigger) - auto0 - ;; - 3) # Automatic mode variation 0 (photosensitive epilepsy/stimulation overload trigger) - auto1 - ;; - 4) # grow shrink mode - growshrink0 - ;; - 5) # grow shrink mode variation 0 - growshrink1 - ;; - 6) # hypnotic mode (photosensitive epilepsy/stimulation overload trigger) - hypno - ;; - 7) # stimulation / calming mode - stim - ;; - 8) # normal mode (aka Judges' Normal) - norm - ;; - 9) # 100ms w/o cheat modes (Judges' Zeroth) - judges0 - ;; - 10) # 75ms w/both cheat modes (Judges' First) - judges1 - ;; - 11) # Immediately win (Judges' Second) - judges2 - ;; - 12) # 50ms w/both cheat modes, evade at 200 moves (Judges' Third) - judges3 - ;; - 13) # 75ms w/both cheat modes, shrink mode (win with six bugs) (Judges' Fourth) - judges4 - ;; - 14) # Let computer win by itself very quickly (Judges' Fifth) - judges5 - ;; - 15) # Start at 400, shrink by 5 every 100 moves, cannibalism and max size possible - growshrink3 - ;; - 16) # Start at 400, shrink by 5 every 100 moves and max size possible - growshrink4 - ;; - *) - exit 0 - esac + while true; do + menu + read -rp "Make your selection (0 - 7 or any other key to exit): " mode + + case "${mode}" in + 0) # Drawing mode 0 + draw0 + ;; + 1) # Drawing mode 1 + draw1 + ;; + 2) # Automatic mode (computer plays by itself) (photosensitive epilepsy/stimulation overload trigger) + auto0 + ;; + 3) # Automatic mode variation 0 (photosensitive epilepsy/stimulation overload trigger) + auto1 + ;; + 4) # grow shrink mode + growshrink0 + ;; + 5) # grow shrink mode variation 0 + growshrink1 + ;; + 6) # hypnotic mode (photosensitive epilepsy/stimulation overload trigger) + hypno + ;; + 7) # stimulation / calming mode + stim + ;; + 8) # normal mode (aka Judges' Normal) + norm + ;; + 9) # 100ms w/o cheat modes (Judges' Zeroth) + judges0 + ;; + 10) # 75ms w/both cheat modes (Judges' First) + judges1 + ;; + 11) # Immediately win (Judges' Second) + judges2 + ;; + 12) # 50ms w/both cheat modes, evade at 200 moves (Judges' Third) + judges3 + ;; + 13) # 75ms w/both cheat modes, shrink mode (win with six bugs) (Judges' Fourth) + judges4 + ;; + 14) # Let computer win by itself very quickly (Judges' Fifth) + judges5 + ;; + 15) # Start at 400, shrink by 5 every 100 moves, cannibalism and max size possible + growshrink3 + ;; + 16) # Start at 400, shrink by 5 every 100 moves and max size possible + growshrink4 + ;; + *) + exit 0 + esac + read -rp "Do you want to continue? " ans + + if [[ "$ans" != "y" && "$ans" != "Y" ]]; then + break; + fi + done } play diff --git a/2020/ferguson1/snake.1 b/2020/ferguson1/snake.1 index 0f685f87e..273f2f124 100644 --- a/2020/ferguson1/snake.1 +++ b/2020/ferguson1/snake.1 @@ -2,50 +2,27 @@ .SH NAME snake \- Feature\-rich curses implementation of the classic 'Snake' game with many gameplay modes and options for IOCCC 2020 .SH SYNOPSIS -\fBsnake\fP +\fBWAIT\fP=\fIN\fP \fBWALLS\fP=\fI[01]\fP \fBEVADE\fP=\fIN\fP \fBSIZE\fP=\fIN\fP \fBMAXSIZE\fP=\fIN\fP \fBGROW\fP=\fIN\fP \fBSHEDS\fP=\fIN\fP \fBSHED\fP=\fIN\fP \fBCANNIBAL\fP=\fI[01]\fP ./snake +.br +# start pressing some arrow keys +.br +where +.I N +is a number and +.I [01] +is either +.I 1 +or +.I 0 +(or more correctly zero and non-zero). .SH DESCRIPTION -\fBsnake\fP has two cheat modes (passable walls/self[cannibalism]), a drawing/practising mode, \fIcan play by itself\fP (\fBand win!\fP), is coloured (included \fIsnake-colours.sh\fP and \fIplay.sh\fP scripts compile in player\-selected colours) and there are many other play modes (many more can be devised with the imagination and the environmental variables; see \fbENVIRONMENT\fP and the file \fIgameplay.md\fP for many examples) and options. +\fBsnake\fP has two cheat modes (passable walls/self[cannibalism]), a drawing/practising mode, \fIcan play by itself\fP (\fBand win!\fP), is coloured (included \fIsnake-colours.sh\fP and \fIplay.sh\fP scripts compile in player\-selected colours) and there are many other play modes (many more can be devised with the imagination and the environmental variables; see \fBENVIRONMENT\fP and the file \fIgameplay.md\fP for many examples) and options. You can pause and there's even a built\-in test unit for some features! -Some of the configurable features are: +.PP +Besides the environmental variables (described below) that create for a lot of gameplay modes, here are some additional features: .PP .RS -\fB\-\fP The speed of the snake (how many milliseconds to \fBWAIT\fP for input before moving; \fIdefault 231 milliseconds\fP and you can move faster by pressing the direction key quicker or or even holding it down). -.RE -.PP -.RS -\fB\-\fP If the bug (to eat) will move (\fBEVADE\fP) after user\-specified number of snake moves (\fIdefault 300, 0 disables\fP). -.RE -.PP -.RS -\fB\-\fP If the snake can go through \fBWALLS\fP (coming out at the opposite wall) (\fIdefault 1, yes\fP). -.RE -.PP -.RS -\fB\-\fP If the snake can go through itself (\fBCANNIBAL\fP) (\fIdefault 0, no\fP). -.RE -.PP -.RS -\fB\-\fP The initial \fBSIZE\fP of the snake (\fIdefault 5\fP). -.RE -.PP -.RS -\fB\-\fP The size the snake must become in order to win the game (\fBMAXSIZE\fP, \fIdefault 997\fP). -.RE -.PP -.RS -\fB\-\fP How much to \fBGROW\fP each time a bug is eaten (\fIdefault 5\fP, can be negative). -.RE -.PP -.RS -\fB\-\fP How many moves (\fBSHED\fP, \fIdefault 0, disabled\fP) before 'stretching' (grow) (\fBSHEDS\fP, \fIdefault 5\fP; can be negative). -This is how snakes grow in the wild so is a misnomer here because snakes don't grow in the manner that the original Snake game was designed. -.RS -\fB\- Exception\fP: If the bug is eaten the counter isn't incremented. -.RE -.RE -.PP -.RS -\fB\-\fP A drawing mode (\fBWAIT < 0\fP makes \fBtimeout()\fP set blocking read). +\fB\-\fP A drawing mode (\fBWAIT < 0\fP makes \fBtimeout()\fP block). .RE .PP .RS @@ -58,10 +35,6 @@ This is how snakes grow in the wild so is a misnomer here because snakes don't g .RE .PP .RS -\fB\-\fP The dimensions of the game (this is actually a terminal thing but I document how to do this and its potential pitfalls) (\fBLINES\fP, \fBCOLUMNS\fP). -.RE -.PP -.RS \fB\-\fP Different colours and characters for the bug, snake head, snake and walls: .RS \fB\-\fP Bug is \fB*\fP (white). @@ -81,69 +54,89 @@ This is how snakes grow in the wild so is a misnomer here because snakes don't g The options are specified via the environmental variables. .SH ENVIRONMENT The following environmental variables modify the behaviour of the game: +.TP +.B WAIT +positive or negative integer that changes how long to wait for a key press prior to moving again. +< 0 blocks which allows for complete control over movement at your own pace. +Default 231; you can move faster by holding down or rapidly pressing an arrow key. +.TQ +.B WALLS +whether the walls are passable or impassable. +Default 1, passable; 0 means impassable and you will die if you hit a wall. +.TQ +.B EVADE +how many movements the Snake makes before the bug (well insect) will move to another location in the field. +Default 300; 0 disables. +.TQ +.B SIZE +initial size of the Snake. +Default 5. +Note that it grows by one per move so at the default 5 it will not initially be 5 characters long! +< 0 is an immediate win. +.TQ +.B MAXSIZE +the maximum size the Snake can become before the game is won. +< 0 is the maximum size based on terminal dimensions; any other size will be capped based on the terminal dimensions to prevent problems. +Note that when +.B SIZE + GROW >= MAXSIZE +you win +.I before +you grow to the full size! +.TQ +.B GROW +size to grow every time you eat a bug. +Default 5; can be negative. +"Negativity" creates for fun gameplay modes with enough creativity. +See \fIgameplay.md\fP/\fIgameplay.html\fP for some examples. +\fIplay.sh\fP allows you to reconfigure the colours and play different pre\-configured gameplay modes. +.TQ +.B SHED +every +.B SHED +movements you will grow (> 0), shrink (< 0) or stay the same length (0) by the +.B SHEDS +(below) value. +Default 0. +Again with creativity you can create some fun gameplay modes. +NOTE: the concept of shedding in this game is a misnomer. +\fB\- Exception\fP: if the bug is eaten the counter isn't incremented. +This is how snakes grow in the wild so is a misnomer here because snakes don't grow in the manner that the original Snake game was designed. +.TQ +.B SHEDS +every +.B SHED +movements will impact what this value means: grow (> 0), shrink (< 0) or not at all (0). +Default 0. +Again with creativity you can create some fun gameplay modes here. +For instance you can grow upon eating a bug but shrink every +.B SHED +movements and then it's a battle of whether you win by +.B SIZE +< 0 +or +.B SIZE +>= +.B MAXSIZE\c +\&. +See +.I play.sh +and +.I gameplay.html +for examples. +\fB\- Exception\fP: if the bug is eaten the counter isn't incremented. +NOTE: the concept of shedding in this game is a misnomer. +\fB\-\fP How many moves (\fBSHED\fP, \fIdefault 0, disabled\fP) before 'stretching' (grow) (\fBSHEDS\fP, \fIdefault 5\fP; can be negative). +This is how snakes grow in the wild so is a misnomer here because snakes don't grow in the manner that the original Snake game was designed. .PP -\fBGROW\fP -.RS -How much to grow each time a bug is eaten. -Negative growth is a different gameplay mode. -\fIDefault 5\fP. -.RE -\fBSIZE\fP -.RS -The initial size of the snake. -\fIDefault 5\fP. -.RE -\fBMAXSIZE\fP -.RS -The max snake size (the size the snake must become to win). -\fIDefault 997\fP. -Limits are always imposed depending on the size of the terminal. -Negative number sets to max size based on terminal size. -.RE -\fBWAIT\fP -.RS -The number of milliseconds to wait for input (how fast the snake moves). -\fIDefault 231\fP. -\fI0\fP has no delay: the computer will play by itself (though you can still change directions). -\fI< 0\fP is drawing mode (makes \fIgetch()\fP block). -.RE -\fBEVADE\fP -.RS -The number of movements before the bug tries to move to a new place (evading the snake). -\fIDefault 300\fP (0 disables). -.RE -\fBWALLS\fP -.RS -Whether the snake can go through walls. -\fIDefault 1\fP (yes). -.RE -\fBCANNIBAL\fP -.RS -Whether the snake can go through itself. -\fIDefault 0\fP (no). -.RE -\fBSHED\fP -.RS -How many moves before the snake 'moults' (shedding of skin to make room for growth). -Again this isn't technically accurate in Snake. -\fIDefault 0\fP (disabled). -.RE -\fBSHEDS\fP -.RS -The amount to grow by each time the snake sheds its skin. -\fIDefault 5\fP. -.RE -.PP -The following two modify the terminal dimensions (this is not part of the game but the terminal/curses itself): -.PP -\fBLINES\fP -.RS +The following two modify the terminal dimensions (this is not part of the game but the terminal/curses itself). +Elsewhere I document these more and their potential pitfalls. +.TP +.B LINES The number of rows. Default is the maximum size of the current terminal size (\fBecho $LINES\fP will show the current value). Please note that this is not the number of playable rows but the entire game itself. -.RE -\fBCOLUMNS\fP -.RS +.TQ +.B COLUMNS The number of columns. Default is the maximum size of the current terminal size (\fBecho $COLUMNS\fP will show the current value). Please note that this is not be the number of playable columns but the entire game itself. @@ -155,7 +148,7 @@ The markdown files have html counterparts; for some of these the html version is .RS Source file to the Snake game (IOCCC entry source file). .RE -\fIremarks.markdown\fP +\fIREADME.md\fP .RS Describes what the entry (game) is, what it looks like, how to play etc. Includes a variety of other information as well as NAQs (never asked questions that I believe could actually be asked so perhaps better would be infrequently asked questions, IAQs). @@ -172,16 +165,16 @@ Information to help work out any possible problems as well as show how to config .RS A troubleshooting guide focusing more on terminals. .RE -\fICOMPILING\fP +\fICOMPILING.md\fP .RS Information on Portability, C standards as well as (for the IOCCC judges) both Justifications for certain things and lints. .RE -\fIHACKING\fP +\fIHACKING.md\fP .RS Documentation on how to modify the input keys, colours, wall, bug and snake chars (to print), the status/score line and various other things. Includes feature ideas as well as how one might implement them. .RE -\fIspoilers.markdown\fP +\fIspoilers.md\fP .RS Technical details that give more away about how the program works (\fIHACKING\fP also does a bit of this). .RE @@ -189,7 +182,7 @@ Technical details that give more away about how the program works (\fIHACKING\fP .RS To build the terminal capabilities test utility and the Snake game itself. .RE -\fIsnake-colours\fP +\fIsnake-colours.sh\fP .RS Helper script to compile the game with player selected colours. .RE @@ -197,7 +190,7 @@ Helper script to compile the game with player selected colours. .RS List of bugs and things that might appear to be bugs that aren't, were once bugs etc. .RE -\fIchocolate\-cake.markdown\fP +\fIchocolate\-cake.md\fP .RS The judges love chocolate and who can blame them? This is something of a speciality of my mum's but it's a delicious cake that even my late stepmum (who only liked white chocolate) loved! Double\-layer chocolate fudge cake. .RE @@ -210,13 +203,13 @@ Source file to test terminal support for the used capabilities the Snake game us See this file to see the manual i.e. this file. Don't get lost in the snake pit! .RE -\fIcannibalism.log\fP +\fIcannibalism.log.md\fP .RS A screen dump of what cannibalism can look like right before winning. .RE -\fIcrazy.log\fP +\fIcrazy.log.md\fP .RS -A screen dump of the positive/push - negative/shrink mode. +Screen dumps of the positive/push - negative/shrink mode. .RE \fIplay.sh\fP .RS @@ -231,21 +224,16 @@ It also clears the screen before playing to try and maintain terminal sanity sho .RE .RE .SH BUGS -.RS -\fB\-\fP The screen keeps showing bugs! -.RE -.RS -\fB-\fP There's no boss screen. -.RE -.RS -\fB\-\fP It was written by a human being. -.RE -.RS -\fB\-\fP Technically walls, snakeskin and the snake itself would \fBnot\fP be an obstacle in real life. +\fB\-\fP the screen keeps showing bugs! +.br +\fB\-\fP there's no boss screen. +.br +\fB\-\fP it was written by a human being. +.br +\fB\-\fP technically walls, snakeskin and the snake itself would \fBnot\fP be an obstacle in real life. The shed snakeskin is not an obstacle but walls can be and so can the snake itself. Also snakes grow by moulting (technical term for shedding) so when the snake leaves its snakeskin behind it really ought to grow but instead it shrinks; this means negative shedding ought to have the snake grow and positive shedding have the snake - what? It's a misnomer: it took fewer bytes and the negative shedding is a positive consequence of unsigned arithmetic. -.RE .PP On a more serious note see the \fBbugs.md\fP file. .SH EXAMPLES @@ -300,4 +288,4 @@ For more gameplay information and modes check \fIgameplay.md\fP; and for an inte Written by Cody Boone Ferguson for IOCCC 2020 (the 27th IOCCC). .SH SEE ALSO .PP -\fB\\fP The 27th IOCCC 'Don't tread on me award'. +\fB\\fP The 27th IOCCC 'Don't tread on me' award. diff --git a/2020/ferguson1/spoilers.md b/2020/ferguson1/spoilers.md index 03254de0e..d1ec2f0e6 100644 --- a/2020/ferguson1/spoilers.md +++ b/2020/ferguson1/spoilers.md @@ -1,6 +1,6 @@ # Introduction (SPOILER ALERT) -In the [gameplay.md][] ([gameplay.html][]) file I have given enough +In the [gameplay.html][] ([gameplay.md][] on GitHub) file I have given enough information to know how the game looks, how to move the snake, how to pause etc. In this file I am including (some) information on how the game actually works: the technical details as it were, obfuscation techniques and also some of the @@ -38,10 +38,10 @@ already knew that so no harm there, hey? The gameplay I have already described but this explains the way things are actually done in more detail. -First I initialise curses; if this fails I print an error message ('curses -error') and return 1. Next the screen size is determined and I subtract 1 from -both x/y. If it's too small curses is ended and an error message ('screen -too small') is printed - returning 1. +First I initialise curses; if this fails I print an error message (`curses +error`) and return 1. Next the screen size is determined and I subtract 1 from +both `x`/`y`. If it's too small curses is ended and an error message (`screen +too small`) is printed - returning 1. Next the max size of the snake is determined: if `MAXSIZE` is specified then it's the value of that; otherwise it's the default. But in either case if it's @@ -49,18 +49,18 @@ too big based on the screen dimensions it's capsized. The arrays for the snake are this size + 1. Other environmental variables are also processed. Then the arrays are allocated; if either return NULL curses is ended, an error -message ('memory error') is printed and return 1. +message (`memory error`) is printed and return 1. If no errors have occurred I set up colours, turn on bold, set up the keypad etc., place the snake, the bug, draw the walls and then it waits for the first move (or quit of course). Technically I don't 'wait' for input as such: unless the wait time is negative (drawing mode) it's just a non-blocking call up to the -WAIT milliseconds but in no event will the snake move until it is told to at +`WAIT` milliseconds but in no event will the snake move until it is told to at least once (in drawing mode it will always wait). In drawing mode if you pause then when you resume (hit space) the snake will move the last direction it had been told to move - because the direction is set -and input was detected (the same goes for another key e.g. 'g' - just like in +and input was detected (the same goes for another key e.g. `g` - just like in normal mode). But it will then wait again for input. The snake function both draws the snake and updates the arrays; if the new size @@ -85,9 +85,9 @@ loses/quits/wins) the movement proceeds; if the game hasn't started yet it will jump to the top of the loop. If it's paused the same thing until it's resumed. The rest of the loop can be described thusly. -It checks the current max y/x, draws the walls, bug, gets any input from +It checks the current max `y`/`x`, draws the walls, bug, gets any input from keyboard, and then if there is movement checks for collisions; if current max -x/y are is/are smaller than original then it's automatically a game over from +`x`/`y` are is/are smaller than original then it's automatically a game over from running into walls regardless of that feature status - this simplifies things greatly (see below for more details). @@ -99,7 +99,7 @@ it's also game over. As the snake moves it will for each move grow by one up to the technical size. This might at times look a bit different from other times but it's a visual -thing based on the internal data of the game and the features enabled for +thing based on the internal state of the game and the features enabled for example shedding and shedding size. Finally if the snake's new coordinates are on a bug a new bug is placed on the @@ -128,13 +128,13 @@ for bugs. # Drawing (manual) and computer playing (automatic) modes -How do these modes work? The `timeout()` function takes a signed int: if it's < -0 it waits indefinitely; if it's 0 it returns immediately even if there's no -input waiting (if input is there then it's used instead); and if it's > 0 it +How do these modes work? The `timeout()` function takes a signed int: if it's `< +0` it waits indefinitely; if it's `0` it returns immediately even if there's no +input waiting (if input is there then it's used instead); and if it's `> 0` it waits that many milliseconds. Thus a negative value allows for complete control -over the snake's movement (speed and otherwise), a value of 0 means the snake +over the snake's movement (speed and otherwise), a value of `0` means the snake will move as long as it's not paused etc. and otherwise it waits up to that many -milliseconds (which is how the 0 value comes into play). +milliseconds (which is how the `0` value comes into play). # Collision detection @@ -149,8 +149,8 @@ verifying if the snake head is at a place that's occupied by the snake, the wall or the bug. The bug does its best to avoid landing where the snake is but given that snakes -are very flexible and cunning who can tell what might happen? As I noted these -bugs are not bugs! :) +are very flexible and cunning who can tell what might happen? As I noted _these +bugs are not bugs! :)_ ## Cannibal collision detection @@ -351,7 +351,7 @@ converted this: (!P && (P = 1))||(P=0); -- Makes use of the different 'namespaces' to have variables and labels be the +- Makes use of the different namespaces to have variables and labels be the same identifier. For example in main() there's a variable that also have the same name label for `goto` (there used to be two pairs in main()). @@ -361,7 +361,7 @@ two loops (a for() in the 'while()'), re-entering (as in starting over) a for() loop and for dealing with errors. - Why do I check for `Q || P` and then goto x only to then check for `!Q && !D` -to then goto x? Do I need to check Q at all? In fact I do but at a quick glance +to then `goto x`? Do I need to check `Q` at all? In fact I do but at a quick glance it might be easy to miss. - Uses an unnamed array (compound literal) for several different game variables. @@ -437,13 +437,14 @@ dimensions. Now in the first call in main() I have the code and tests following: offsets for every time I use negative offsets. But where's the fun in that? :) - BTW: Some of these are not in the table of expressions in the HACKING file. - Also there might be some code in there that is no longer correct (it was - before I started obfuscation) though it might be able to give an idea. - Spoilers abound in that file (in addition to this file) but the HACKING file - states things that are no longer true: a way of obfuscation itself! Instead - of misleading comments it's misleading statements in the file that explains - what some of the things are for! + BTW: Some of these are not in the table of expressions in the + [HACKING.html][] ([HACKING.md][] on GitHub) file. Also there might be some + code in there that is no longer correct (it was before I started + obfuscation) though it might be able to give an idea. Spoilers abound in + that file (in addition to this file) but the [HACKING.html][] ([HACKING.md][] + on GitHub) file states things that are no longer true: a way of obfuscation + itself! Instead of misleading comments it's misleading statements in the + file that explains what some of the things are for! - Misleading variable names for coordinates. In other words the Y coordinate is called X and the X coordinate is called Y. This adds to the already confusing @@ -731,7 +732,7 @@ simply return E() and thus it's only called once. Similarly for `Q` I set it to top of the code and then in main() assigned like: `l = ++(int) { 3 } ;` which equates to 4. I think that's pretty cool! -- What is this? `for(I=0; A&&I 0 so `A-A` is 0; however because `A` is non-zero the expression `A-A||A` is equivalent to `0 || A` and since A is non-zero we know that the value is `1` and thus it's `A - 1`! I quite like this @@ -818,25 +819,29 @@ Another thing that reduced a lot of bytes - 34 to be exact - is using the `mvvline()` and `mvhline()` ncurses functions rather than use three for loops to draw the walls. -Much later on I made it so that the E() function returns 1; this was a clever +Much later on I made it so that the `E()` function returns 1; this was a clever way to have what I already did have - return 1 if there's an error (i.e. memory error or curses error or screen too small) but otherwise return 0 without having to have a separate int and I could get rid of two `{}` pairs as well as add -another use for the E() function: it calls endwin() exactly once (even though +another use for the `E()` function: it calls endwin() exactly once (even though when there isn't an error condition it can be called more than once) as well as printing the final score - or else an error. And now it also allows for printing an error and returning from main() at the same time! This also means that by -returning E() I am returning 1 but if the end of main() is reached 0 is +returning `E()` I am returning 1 but if the end of main() is reached 0 is returned. In either case curses is ended. One of these optimisations saved four bytes simply by taking advantage of the value of a loop iterator after the loop. The loop is: - for (I = 0; A && I < A - 1; ++I) +```c +for (I = 0; A && I < A - 1; ++I) +``` However after the loop I had this: - A > 1 && q(n[A - 1],e[A - 1], 'o'); +```c +A > 1 && q(n[A - 1],e[A - 1], 'o'); +``` When I was considering moving that line to before the loop it occurred to me that as long as `A > 0` then `A - 1 == I` after the loop. I still had to check @@ -857,43 +862,54 @@ the problem. First, the function that turns on colours looked like: - if (h) attron(m(PAIR(L))); - else attroff(m(PAIR(L))); +```c +if (h) attron(m(PAIR(L))); +else attroff(m(PAIR(L))); +``` But I thought is that else actually needed? If I were to switch the order so that the `attroff()` is called first then I could just do an `if (h)` - therefore getting rid of the `else`! But then I thought why not do what I've done elsewhere? I had: - attroff(m(PAIR(L))); - if (h) attron(m(PAIR(L))); +```c +attroff(m(PAIR(L))); +if (h) attron(m(PAIR(L))); +``` But I then saved an extra byte by making it: - attroff(m(PAIR(L))); - h && attron(m(PAIR(L))); +```c +attroff(m(PAIR(L))); +h && attron(m(PAIR(L))); +``` That saved two bytes. -Second let's look at the B() function: there were two things I thought of that +Second let's look at the `B()` function: there were two things I thought of that would save some bytes (I no longer know how many but a few at least possibly six or even more). I had the following code: - if (V && U && o) { S(N); b(1); } +```c +if (V && U && o) { S(N); b(1); } +``` This made sure that only if the snake has caught a bug should it grow by the growth size and increase the bug count. But was checking for the `V` or `U` -necessary? I gave it a look over and it occurred to me: the only time B() is +necessary? I gave it a look over and it occurred to me: the only time `B()` is called with `1` (thus `o` is 1 so the if is true) was if the bug actually is caught. That means I could remove the `V && U &&` part of the if! Thus it became instead: - if (o) { S(N); b(1); } - +```c +if (o) { S(N); b(1); } +``` Then this - !o && V && U && q U,V,' '); +```c +!o && V && U && q U,V,' '); +``` ...is to make sure to only clear the spot the bug is (or was) at if the bug was NOT eaten. Why not eaten? Because if it was eaten it means the @@ -912,7 +928,9 @@ where the snake already is. So if I had to make sure the game had started (the snake has moved at least once) what could I check? In fact that means the direction is not 0! So I could just replace it with: - !o && D && q *U,*V,' '); +```c +!o && D && q *U,*V,' '); +``` That reduced the count further. But then I wondered if even that much is needed. The condition is that the bug has evaded which means the snake has moved already @@ -927,20 +945,23 @@ the score line is updated: so the empty space will be overwritten anyway. And if the score line is made an empty string it doesn't matter because it'll appear as all spaces anyway. Thus I could save another three bytes by changing it to: - !o && q *U,*V,' '); +```c +!o && q *U,*V,' '); +``` -Technically it would be a `" "` (see [HACKING][] file) else for N (not referring to -the variable though it might very well matter here too) movements (i.e. due to -sizes) you will at times (e.g. after eating a bug) see the snake body char at -0,0. I'm not bothered about that though because the score line is meant to -display something, it squeezes a few more bytes and having a space is hardly an -imposition on usage (and for that matter having a 'o' at 0,0 isn't either). +Technically it would be a `" "` (see [HACKING.html][] or on GitHub +[HACKING.md][]) else for N (not referring to the variable though it might very +well matter here too) movements (i.e. due to sizes) you will at times (e.g. +after eating a bug) see the snake body char at 0,0. I'm not bothered about that +though because the score line is meant to display something, it squeezes a few +more bytes and having a space is hardly an imposition on usage (and for that +matter having a 'o' at 0,0 isn't either). [gameplay.md]: gameplay.md [gameplay.html]: gameplay.html -[COMPILING]: COMPILING -[HACKING]: HACKING +[HACKING.md]: HACKING.md +[HACKING.html]: HACKING.html ----------------------------------------------------------------------------------------------------- (c) Copyright 1984-2020, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved diff --git a/2020/ferguson1/termcaps.c b/2020/ferguson1/termcaps.c index 024615700..65818ec7b 100644 --- a/2020/ferguson1/termcaps.c +++ b/2020/ferguson1/termcaps.c @@ -1,11 +1,13 @@ -/* This will imperfectly: - - (1) Test if terminal supports the features Snake uses. - (2) Report terminal (and playing) size(s). - (3) Estimates the minimum number of columns to play unhindered (based on the - size, max size and growth rate). - (4) Reports the max size of the Snake and the number of bugs required to - reach that size (doesn't use shedding). +/* ioccc/2020/ferguson1 - Snake terminal testing utility + * + * This will imperfectly: + * + * (0) Test if terminal supports the features Snake uses. + * (1) Report terminal (and playing) size(s). + * (2) Estimates the minimum number of columns to play unhindered (based on the + * size, max size and growth rate). + * (3) Reports the max size of the Snake and the number of bugs required to + * reach that size but doesn't use shedding. */ #include @@ -84,7 +86,7 @@ int main(void) { i[caps].sup = tigetstr(caps[i].caps); /* tigetstr() returns (char *)-1 if the capability name isn't - * recognised; check for this before suggesting it's supported: */ + * recognised; check for this before suggesting it's (un)?supported: */ if (caps[i].sup == (char *)-1) caps[i].sup = NULL; if (!caps[i].sup) ++k; @@ -119,10 +121,10 @@ int main(void) rows = 14 + b(Y)*2 + a(y)*2 + a(x)*2 + b(N); if (x < (int)rows + 1) ++k; - printf("at least %zu columns recommended for snake size %-5zu (is %d)\n", rows+1,Y, x); + printf("at least %zu columns (currently %d) recommended for snake size %-5zu\n", rows+1,x, Y); rows = 14 + b(K)*2 + a(y)*2 + a(x)*2 + b(c(K,X)); - printf("at least %zu columns recommended for snake size %-5zu (is %d)\n\n", rows + 1, K, x); + printf("at least %zu columns (currently %d) recommended for capped snake size %-5zu\n\n", rows + 1,x, K); if (!k) diff --git a/2020/ferguson1/terminals.md b/2020/ferguson1/terminals.md index bc85fc516..a30827664 100644 --- a/2020/ferguson1/terminals.md +++ b/2020/ferguson1/terminals.md @@ -42,54 +42,68 @@ for the capabilities I use in the entry. It also tries to determine the minimum number of columns to play without the status line overflowing - even with the dynamic length. Try: - $ make test +```sh +$ make test +``` -This compiles the program and runs it; you should see something like: +This compiles the program [termcaps.c](termcaps.c) and runs it; you should see something like: - terminal supports cursor movement - terminal supports making cursor invisible - terminal supports bold - terminal supports colours - terminal rows 42 (39 playable) - terminal cols 157 (155 playable) +``` +terminal supports cursor movement +terminal supports making cursor invisible +terminal supports bold +terminal supports colours - snake size: 997 (max size: 6006) - bugs: 199 (max size: 1201) +terminal rows 41 (38 playable) +terminal cols 155 (153 playable) - at least 34 columns recommended for snake size 997 (is 157) - at least 37 columns recommended for snake size 6006 (is 157) +snake size: 997 (max size: 5776) + bugs: 199 (max size: 1155) - No problems detected. +at least 34 columns (currently 155) recommended for snake size 997 +at least 37 columns (currently 155) recommended for capped snake size 5776 -If I pass in any of the variables **GROW**, **MAXSIZE**, **SIZE** and/or -**LINES** or **COLUMNS** it bases its calculations on those variables. For +No problems detected. +``` + +Terminal rows and cols are the current values (the number of columns shown later +as well). The snake size is the default size to win (based on the variables, see +below). The `max size: 5776` is the capped size (or 'capsize'). The 199 bugs is +approximately the `snake_size / growth_size` i.e. how many bugs it +will take to win the game. The max bugs in the `bugs` line is approximately +`max_snake_size / growth_size` i.e. how many bugs it'll take to win at the +maximum (capped) snake size. + +If I pass in any of the variables **`GROW`**, **`MAXSIZE`**, **`SIZE`** and/or +**`LINES`** or **`COLUMNS`** it bases its calculations on those variables. For example: - $ MAXSIZE=-1 GROW=1 make test - terminal supports cursor movement - terminal supports making cursor invisible - terminal supports bold - terminal supports colours +```sh +terminal supports cursor movement +terminal supports making cursor invisible +terminal supports bold +terminal supports colours - terminal rows 42 (39 playable) - terminal cols 157 (155 playable) +terminal rows 41 (38 playable) +terminal cols 155 (153 playable) - snake size: 6006 (max size: 6006) - bugs: 6001 (max size: 6001) +snake size: 5776 (max size: 5776) + bugs: 5771 (max size: 5771) - at least 37 columns recommended for snake size 6006 (is 157) - at least 37 columns recommended for snake size 6006 (is 157) +at least 37 columns (currently 155) recommended for snake size 5776 +at least 37 columns (currently 155) recommended for capped snake size 5776 - No problems detected. +No problems detected. +``` - -As you can see it tells you the max size (the 'capsized' snake) as well as -the requested max size (if the requested size is bigger than the capsize then it +As you can see it tells you the max size (the 'capsized' snake) as well as the +requested max size (if the requested size is bigger than the capped size then it will be set to that value instead) of the snake. The capped size is like in the Snake game itself but the suggested minimum number of columns is based on a number of variables. + If I were to do the above but set columns to less < 35 then there would be a problem. But why if the utility recommends at least 37? This is because the max size of the snake also depends on the terminal size. This utility is not @@ -108,7 +122,7 @@ this should give you an idea. If there are any problems it will say how many (fatal and otherwise). The fatal problems are if curses fails to initialise or if movement of cursor cannot be -done (both seem odd). +done (both seem unlikely to happen nowadays). Both scripts run this utility and prompt if there are any problems; you can continue either way. @@ -218,8 +232,8 @@ properly. Because that's what funny means in this context. It'd be nice if curses could detect hitting more than one arrow key at the same time so that diagonal directions would be possible but unfortunately it's not (`cat -v` confirms this). Even if I were to define four extra keys what -would they be? And what about the head character? The HACKING file has -information on this. +would they be? And what about the head character? The [HACKING.html][] +([HACKING](HACKING.md) on GitHub) file has information on this. I also limit the terminal size to 10 lines/columns but most likely it would require the cheat modes to win and in any event allowing certain low values @@ -241,7 +255,8 @@ from a quick test this holds even with a terminal that has a white background. There is a way to force the background to remain white though that's by way of monochrome (so no colours); I discuss that and another related terminal specific in the troubleshooting guide (there's another way but it would take me over the -iocccsize; I talk about it in the HACKING file). +iocccsize; I talk about it in the [HACKING.html][] ([HACKING](HACKING.md) on +GitHub) file). ## Monochrome terminals @@ -349,6 +364,8 @@ Perhaps you only need to add the `return;` to `C()`. My guess is that's the case but I do not know for certain. +[HACKING.md]: HACKING.md +[HACKING.html]: HACKING.html [Linux keyboard and console HOWTO]: https://www.tldp.org/HOWTO/Keyboard-and-Console-HOWTO.html [Linux keyboard and console HOWTO section 4]: https://www.tldp.org/HOWTO/Keyboard-and-Console-HOWTO-4.html [snake-colours.sh]: snake-colours.sh diff --git a/2020/ferguson1/troubleshooting.md b/2020/ferguson1/troubleshooting.md index 81498a2e8..86f54c930 100644 --- a/2020/ferguson1/troubleshooting.md +++ b/2020/ferguson1/troubleshooting.md @@ -37,8 +37,8 @@ it as structured as possible/easiest to find. Because the score line is dynamic in length depending on the terminal size it can happen that the score/status wraps to the next line(s). This can be fixed by -modifying the status line (see [HACKING][]) but you shouldn't need it to be very -wide. +modifying the status line (see [HACKING.html][] or on GitHub [HACKING.md][]) but +you shouldn't need it to be very wide. * RESOLUTION #0: Use a bigger screen (it doesn't take that many columns) @@ -58,9 +58,10 @@ wide. #define J Z(B:%zu\n), c); - Recompile and try again. That will then show only the number of bugs eaten. See - the HACKING file for other data you can include (though there are some - discrepancies here and there as you'll see). + Recompile and try again. That will then show only the number of bugs eaten. + See the [HACKING.html][] ([HACKING.md][] on GitHub) file for other data you + can include (though there are some discrepancies here and there as you'll + see). ## The snake isn't moving! @@ -90,7 +91,8 @@ e.g. when the snake is growing. numerous causes for this some of which are a busy computer but ultimately it'll catch up; just give it the time it needs. -* BOTTOM LINE: If you want more information then see the [bugs.md][] file. +* BOTTOM LINE: If you want more information then see the [bugs.html][] +([bugs.md][] on GitHub) file. ## I can't see the snake head (or other part of the snake)! @@ -210,18 +212,18 @@ snake. See below for some tests. terminal supports bold terminal supports colours - terminal rows 42 (39 playable) - terminal cols 157 (155 playable) + terminal rows 41 (38 playable) + terminal cols 154 (152 playable) - snake size: 997 (max size: 6006) - bugs: 199 (max size: 1201) + snake size: 997 (max size: 5738) + bugs: 199 (max size: 1147) - at least 34 columns recommended for snake size 997 (is 157) - at least 37 columns recommended for snake size 6006 (is 157) + at least 34 columns (currently 154) recommended for snake size 997 + at least 37 columns (currently 154) recommended for capped snake size 5738 No problems detected. - Why are there only 39 playable lines for 42 rows? The first row is the score + Why are there only 38 playable lines for 41 rows? The first row is the score line, the second is the top wall, the last is the bottom wall. For columns you have the left and rightmost columns for the walls. @@ -286,7 +288,8 @@ so that's probably why; in CentOS I did have to install it specially. The `-m` suffix to terminal names means monochrome. Under Linux this terminal is under `/usr/share/terminfo/l/linux-m` and under macOS (Catalina - at least) it's at `/usr/share/terminfo/6c/linux-m`. + at least) it's at `/usr/share/terminfo/6c/linux-m` (for macOS Ventura it's + `/usr/share/terminfo/6c/linux-m`). * BOTTOM LINE: Try using a monochrome terminal for the game by e.g.: @@ -295,10 +298,11 @@ so that's probably why; in CentOS I did have to install it specially. And then on your white background terminal the game should keep the background white and the foreground black. This will of course mean you have no colour but unfortunately changing the background colour of curses would - eat too many bytes in the entry (I cite the functions in the HACKING file). + eat too many bytes in the entry (I cite the functions in the + [HACKING.html][] ([HACKING.md][] on GitHub) file). I discuss colours and terminals in much more detail in - [terminals.md][] ([terminals.html][]). + [terminals.html][] ([terminals.md][] on GitHub). ## The text is hard to see (not bright enough)! @@ -335,7 +339,9 @@ hit a key every time to move because it is blocking. What happens if you do: - WALLS= ./prog +```sh +WALLS= ./prog +``` Can you run into the wall since you didn't specify a value and the default is 1? No. That's not the way it works. By saying WALLS= you have told the system that @@ -347,48 +353,61 @@ for a number could have a better value than 0. If however you were to give valid input followed by invalid input the valid input would be parsed. For example: - WALLS=1test ./prog +```sh +WALLS=1test ./prog +``` -Would let you go through the walls. On the other hand +would let you go through the walls. On the other hand - WALLS=test1 ./prog +```sh +WALLS=test1 ./prog +``` -Would not. Furthermore if you specify the same variable more than once it's the +would not. Furthermore if you specify the same variable more than once it's the last one that counts. For example: - WALLS=0 WALLS=1 CANNIBAL=1 CANNIBAL=0 ./prog +```sh +WALLS=0 WALLS=1 CANNIBAL=1 CANNIBAL=0 ./prog +``` -Would allow you to go through walls but you could not cannibalise. +would allow you to go through walls but you could not cannibalise. Also note that I specify base 0 which means that you can also have it in hex and octal. These are all the same: - SIZE=0x3 - SIZE=3 - SIZE=03 +``` +SIZE=0x3 +SIZE=3 +SIZE=03 +``` The way the functions work is if 0x (or 0X) it's considered hex; if prefixed with a 0 it's octal and otherwise it's decimal. If you specify invalid data (even if only at the beginning of the string) the functions return 0. For -example +example: - SIZE=0 - SIZE=f - SIZE=- - SIZE=f1 +``` +SIZE=0 +SIZE=f +SIZE=- +SIZE=f1 +``` -Are all equivalent. +are all equivalent. -Observe that +Observe that: - SIZE=08 +``` +SIZE=08 +``` -Is invalid input because octal only has digits 0 - 7: the resulting size will be +is invalid input because octal only has digits 0 - 7: the resulting size will be 0. I discuss the signed/unsigned issue to do with curses and sizes in C being -unsigned in [bugs.md][] but probably there isn't anything more to say here. +unsigned in [bugs.html][] ([bugs.md][] on GitHub) but probably there isn't +anything more to say here. ## Errors and error reporting @@ -402,33 +421,39 @@ screen size must be at least 10 lines/columns (though in code the number will not be 10); if either is smaller you will get 'screen too small' and the game will end (yes things that haven't begun can be ended). -If calloc() fails to obtain the needed memory you'll see something like (here it +If `calloc()` fails to obtain the needed memory you'll see something like (here it was before I added proper - to make the perfect and obvious pun - capsizing so that by setting the size to -1 it went to the max unsigned value): - $ MAXSIZE=-1 ./prog - memory error - X:0/157 Y:0/42 S:3/18446744073709551614 B:0 +```sh +$ MAXSIZE=-1 ./prog +memory error +X:0/157 Y:0/42 S:3/18446744073709551614 B:0 +``` -BTW: There are two arrays that have to be **MAXSIZE** (technically + 1). +BTW: There are two arrays that have to be **`MAXSIZE`** (technically + 1). Is it possible that some value specified by the user could mess this up? I do not know but what I do know is that because it's unsigned it can't be negative; if the max size is 0 then the array size will be 1 but it won't matter because the snake size will be >= that max anyway. But here's a curious output: - SIZE=1 MAXSIZE=0 ./prog - YOU WIN! - X:78/156 Y:20/41 S:0/0 B:0 +```sh +SIZE=1 MAXSIZE=0 ./prog +YOU WIN! +X:78/156 Y:20/41 S:0/0 B:0 +``` Why does it show snake size as 0 when I specified 1? It's because the max size is 0 and I limit the size to be no bigger than the max size. -[HACKING]: HACKING +[HACKING.md]: HACKING.md +[HACKING.html]: HACKING.html [prog.c]: prog.c [bugs.md]: bugs.md +[bugs.html]: bugs.html [terminals.md]: terminals.md [terminals.html]: terminals.html [snake-colours]: snake-colours diff --git a/2020/ferguson2/.gitignore b/2020/ferguson2/.gitignore index 30e9f5498..7fd89fc87 100644 --- a/2020/ferguson2/.gitignore +++ b/2020/ferguson2/.gitignore @@ -2,3 +2,4 @@ prog recode chocolate-cake.dat chocolate-cake.key +cake.sh diff --git a/2020/ferguson2/README.md b/2020/ferguson2/README.md index 19cc861b8..48315dc7a 100644 --- a/2020/ferguson2/README.md +++ b/2020/ferguson2/README.md @@ -46,7 +46,7 @@ make ``` -**NOTE**: in recode no spaces between options and option arguments are allowed. +**NOTE**: in [recode](recode.c) no spaces between options and option arguments are allowed. ## Try: @@ -82,25 +82,37 @@ rm -f conf input output output2 ``` +What does: + +```sh +echo | ./recode +echo | ./recode -v + +``` + +do? + ## Judges' remarks: -This code is an enigma. Try to decode it! +This code is an [enigma](https://youtu.be/ybkkiGtJmkM). Try to decode it! There is a good deal of useful documentation that is provided with this entry: * [enigma.1](enigma.1) - A useful man page for this entry. To render, try: + ```sh man ./enigma.1 ``` -* [recode.html][] - - Some useful information about recode.c + +* [recode.html][] (or [recode.md](recode.md) if reading on GitHub) + - Some useful information about [recode.c](recode.c) -* [chocolate-cake.html][] - - Because most of us could use some *Double-layered Chocolate Fudge Cake*! - - NOTE: see [recode.html][] for details about how to decrypt this! +* [chocolate-cake.html][] (or [chocolate-cake.md](chocolate-cake.md) if reading on GitHub) + - Because most of us could use some *Double-layered Chocolate Fudge Cake*! + - NOTE: see [recode.html][] (or [recode.md](recode.md) for details about how to decrypt this! [recode.html]: recode.html @@ -108,11 +120,13 @@ There is a good deal of useful documentation that is provided with this entry: ## Author's remarks: -My remarks about my Heer 'Army' and Luftwaffe 'Air Force' Enigma simulator for +My remarks about my [Heer][] (army) and [Luftwaffe][] (air force) [Enigma +machine](https://www.cryptomuseum.com/crypto/enigma/index.htm) [simulator](prog.c) for the 27th IOCCC. I want to dedicate this entry in part to the millions of poor souls that were -lost during the tragedy that is the Second World War. There are so many people +lost during the tragedy that is the [Second World +War](https://en.wikipedia.org/wiki/World_War_II). There are so many people who are unknown, unloved, unclaimed and even unidentified. And who knows what they might have gone on to do if their lives weren't - like it is with all other wars - needlessly taken from them? When one considers it was all because the @@ -122,22 +136,22 @@ makes it somehow even more tragic: there wasn't even a good reason for the war If one were to write the name of every person who died in the conflict in a book, it would take so many pages that the book would be so heavy, so long, so -expensive to print, and it wouldn't bring anyone back to life nor would it -erase the suffering. Nothing will. It's horrible. +expensive to print and it wouldn't bring anyone back to life nor would it erase +the suffering. Nothing will. It's horrible. There really are no words that can truly describe the tragedy but I wish to with -my Enigma simulator honour each and every soul who was lost, or suffered, or +my [Enigma][] simulator honour each and every soul who was lost, or suffered, or suffered the loss of friends or loved ones, as well as the world itself, in and from one of the greatest tragedies in the history of mankind. -I will have more information on this entry at -[https://ioccc.xexyl.net/2020/enigma][] after the winning entries have been -published. +I have more information on this entry like the testing procedure at +. + - [IOCCC: an Enigma?](#ioccc) -- [The 1992 Nathan entry](#nathan) +- [The 1992 Nathan Sidwell entry](#nathan) - [Usage](#usage) * [Example run](#example) @@ -152,7 +166,7 @@ published. - [Bugs, limitations, differences from the real Enigma machines and general notes](#bugs) -- [Adding Kriegsmarine support](#kriegsmarine) +- [Kriegsmarine support?](#kriegsmarine) - [Portability](#portability) @@ -167,59 +181,67 @@ sure there are some other words that are equally as valid but I believe 'Enigma' is a great word nonetheless. However it's curious that no winning entry has ever been a simulator of the -German Enigma machine. I'm actually quite surprised at that because it's such a -brilliant piece of engineering of the time even though it had a critical flaw: -that no letter could be itself; this combined with cribs (known or suspected -plaintext) - which was down to carelessness, capturing an Enigma and sometimes -settings sheet, as well as known messages the Germans started out with - allowed -for cracking the code. +[German Enigma machine](https://en.wikipedia.org/wiki/Enigma_machine). I was +actually quite surprised (though pleased as it gave me the chance to learn about +it and submit and win an entry) at that because it's such a brilliant piece of +engineering of the time even though it had a critical flaw: that no letter could +be itself; this combined with cribs (known or suspected plaintext) - which was +down to carelessness, capturing an Enigma and sometimes settings sheet, as well +as known messages the Germans started out with - allowed for [cracking the +code](https://en.wikipedia.org/wiki/Cryptanalysis_of_the_Enigma). -Combining this entry with two of the Morse code entries is particularly +Combining this entry with two of the [Morse +code](https://en.wikipedia.org/wiki/Morse_code) entries is particularly interesting because that's what the Germans did: the party sending the message would first set up the machine, write down the letters and then transmit by -Morse code the encoded message. Then those picking up on the message would note -the Morse code, translate it to the alphabet and then input it into their Enigma -machine configured in the same way and thus have the original message. +[Morse code](https://en.wikipedia.org/wiki/Morse_code) the encoded message. Then +those picking up on the message would note the Morse code, translate it to the +alphabet and then input it into their Enigma machine configured in the same way +and thus have the original message. -The [1998 ASCII / Morse code translator][] entry (author Dorssel) prints the -Morse code of text; and the [2014 Morse audio transcoder][] (author Vik) can be -used to allow for the actual sound of it. With my entry we can complete the -loop! +The [1998 ASCII / Morse code translator][] entry by [Franz van +Dorsselaer](/winners.html#Frans_van_Dorsselaer) prints the Morse code of text; +and the [2014 Morse audio transcoder][] by [Daniel +Vik](/winners.html#Daniel_Vik) can be used to allow for the actual sound of it. +With my entry we can complete the loop! -### The 1992 Nathan entry +### The 1992 Nathan Sidwell entry -The author (Nathan) of the [1992 Worst Abuse of the Rules][] had this to say: +The author [Nathan Sidwell](/winners.html#Nathan_Sidwell) of the [1992 Worst +Abuse of the Rules][] had this to say about his program: -``` -This program is a hello world text encrypter/decrypter. It uses an -enigma (I think) style encryption algorithm, where the encryption -key character is modified by a value, determined from the previous -character. Non-printable characters (those with ASCII values < ' ' -or > 0x7e) are passed unaltered, thus any kind of file may be -successfully processed, but if the original is printable, the -processed file will be too. The input is read from stdin, and the -output presented to stdout. The key, a text string, is presented as -a command argument. This is optional, and if omitted, the file is -self-{de,en}crypted. To specify decryption, a "-" should be given -before the key. (Actually encryption and decryption proper inverse -operations, so you can use decrypt to scramble and encrypt to -descramble, if you're perverse.) -``` +> This program is a hello world text encrypter/decrypter. It uses an +[enigma](https://www.cryptomuseum.com/crypto/enigma/index.htm) (I think) style +encryption algorithm, where the encryption key character is modified by a value, +determined from the previous character. Non-printable characters (those with +ASCII values `< ' '` or `> 0x7e`) are passed unaltered, thus any kind of file +may be successfully processed, but if the original is printable, the processed +file will be too. The input is read from stdin, and the output presented to +stdout. The key, a text string, is presented as a command argument. This is +optional, and if omitted, the file is self-{de,en}crypted. To specify +decryption, a `-` should be given before the key. (Actually encryption and +decryption proper inverse operations, so you can use decrypt to scramble and +encrypt to descramble, if you're perverse.) -But the Enigma algorithm is more complex than that and my entry can encipher and -decipher text in the manner of the Enigma machines of the Army (Heer) and Air -Force (Luftwaffe); the Kriegsmarine 'Navy' was more complex (see section [Adding -Kriegsmarine support](#kriegsmarine) for more information on that. -My entry should also work as a non-military grade Enigma as it by default has an -empty plugboard (they had none). I explain how to set up the simulator later. +But the Enigma algorithm is more complex than that and my entry can encipher +(and by extension decipher) text in the manner of the Enigma machines of the +[Heer][] (army) and [Luftwaffe](https://en.wikipedia.org/wiki/Luftwaffe) (air +force); the [Kriegsmarine](https://en.wikipedia.org/wiki/Kriegsmarine) (navy; +literally `War Nazy`) was more complex (see section [Kriegsmarine +support?](#kriegsmarine) for more information on that. -Yusuke Endoh asked the judges and me if the real 1992 entry source was -available. Simon Cooper didn't have access to it because it was before his time in -the IOCCC; but before the other judges could answer Ilya Kurdyukov sent a link to -the original 1992 code. As of March 2023 the original before unseen code was -published but I leave this in for historical purposes. +My entry should also work as a non-military grade Enigma; they had no +[plugboard](https://www.cryptomuseum.com/crypto/enigma/i/sb.htm) and by +default mine is empty. I explain how to set up the simulator later. + +[Yusuke Endoh](/winners.html#Yusuke_Endoh) asked the judges and me if the real +1992 entry source was available. Simon Cooper didn't have access to it because +it was before his time in the IOCCC; but before the other judges could answer +[Ilya Kurdyukov](/winners.html#Ilya_Kurdyukov) sent a link to the original 1992 +code. As of 4 March 2023 the original before unseen code was published but I +leave this in for historical purposes. ### Usage @@ -236,24 +258,30 @@ If you run it like: It will prompt you for the settings of the machine (example below). -The first group is in the order of rotor (number), ring setting (letter) and +The first group is in the order of +[rotor](https://www.ciphermachinesandcryptology.com/en/enigmatech.htm) (number), +[ring setting](https://en.wikipedia.org/wiki/Enigma_rotor_details#Ring_setting) (letter) and ring (starting) position (letter). It will do this for the first, second and then third for each. -Then it will prompt you for the reflector (number). The first one is reflector B -and the second is reflector C. +Then it will prompt you for the +[reflector](https://www.ciphermachinesandcryptology.com/en/enigmatech.htm#Reflector) (by number). +The first one is reflector B and the second is reflector C. -Finally it'll prompt you for the plugboard pairs. +Finally it'll prompt you for the [plugboard +pairs](https://www.cryptomuseum.com/crypto/enigma/i/sb.htm). After that you can input the string and it'll go from there. #### Example run BTW: There's a much more entertaining (and delicious) challenge or exercise in -[recode.html][] (involves [chocolate-cake.html][]) though one might need a different -kind of exercise after taking up the challenge! :-) These however show the -general program as well as how to use the two winning entries of the Morse code -that I referred to earlier: +[recode.html][] (if you're reading this on GitHub check the +[recode.md](recode.md) file instead); this involves [chocolate-cake.html][] (if +on GitHub see [here](chocolate-cake.md)) though one might need a different kind +of exercise after taking up the challenge! :-) These however show the general +program as well as how to use the two winning entries of the [Morse +code](https://en.wikipedia.org/wiki/Morse_code) that I referred to earlier: ```sh @@ -305,9 +333,10 @@ If I compile the 2014 entry and copy it to my local directory as $ echo TEST|./prog |./vik | mplayer -demuxer rawaudio - ``` -And you would hear Morse code of the Enigma output of 'TEST' (i.e. `KCWV`)! Or -perhaps not in this case. I'm not sure: I discovered a bug in that entry -(Fedora, CentOS and macOS all affected). +And you would hear [Morse code](https://en.wikipedia.org/wiki/Morse_code) of the +[Enigma](https://www.ciphermachinesandcryptology.com/en/enigmatech.htm) output +of 'TEST' (i.e. `KCWV`)! Or perhaps not in this case. I'm not sure: I discovered +a bug in that entry (Fedora, CentOS and macOS all affected). For example I can use the syntax provided in the winning remarks along with my entry to write it to a file. Say: @@ -342,7 +371,7 @@ TEST I'm not sure what causes that or if there's a way to fix it but that's the idea anyway. Neither do I know if the original transcoding is correct. -What if I use the input string 'LEST' instead? In that case it worked fine: +What if I use the input string `LEST` instead? In that case it worked fine: ```sh $ echo LEST | ./prog | ./vik > lest.raw @@ -366,7 +395,7 @@ Phew! The program redeemed itself after the test failure! :) is with some of the things I pasted in the other file and maybe others here too. Notice also how it showed the same output that my program gave it - `UUMMX`.) -What about the other Morse code entry? +What about the other [Morse code entry](/1998/dorssel/dorssel.c)? ```sh $ echo IOCCC | ./prog | ./dorssel @@ -375,10 +404,15 @@ $ echo IOCCC | ./prog | ./dorssel ### The recode.c configurator -I have included a supplementary program 'recode' ([recode.c][]) that can -do a number of things which acts as a kind of wrapper and configurator to my -entry. By default it prompts you for the settings (rotors/rings, ring settings, -positions, reflector and plugboard pairs), validating input as you go. +I have included a supplementary program [recode.c][] that can do a number of +things which acts as a kind of wrapper and configurator to my entry. By default +it prompts you for the settings +([rotors](https://en.wikipedia.org/wiki/Enigma_rotor_details), [rings and ring +settings](https://en.wikipedia.org/wiki/Enigma_rotor_details#Ring_setting) and +positions, +[reflector](https://www.ciphermachinesandcryptology.com/en/enigmatech.htm#Reflector) and +[plugboard pairs](https://www.cryptomuseum.com/crypto/enigma/i/sb.htm)), +validating input as you go. After that it prompts for text that you can pass to the Enigma simulator; alternatively you can specify a file to read in. @@ -387,25 +421,26 @@ It has a randomise mode and it can save/read the settings to/from a file to allow for duplicity (an archaic term for the state of being double but obviously for Enigma it has to also mean deceitful). -I recommend using this in a pipeline instead of the simulator itself if you want -to change the configuration of the simulator because it offers a much richer -experience (and because you can reuse the configuration without having to type -it out again every time). +I recommend using this in a pipeline instead of the [simulator](prog.c) itself +if you want to change the configuration of the simulator because it offers a +much richer experience (and because you can reuse the configuration without +having to type it out again every time). It does take the effort to try and prevent invalid input (as above) though maybe I didn't think of everything. My entry was meant to be a simulator only as far as the ciphering goes but I thought this would make it much more interesting: make it more flexible by a wrapper program. -For examples using it (and a delicious challenge) see [recode.html][]. See -also [recode.1][] and [enigma.1][] man pages. +For examples using it (and a delicious challenge) see [recode.html][] (or +[recode.md](recode.md) if reading on GitHub). See also the [recode.1][] and +[enigma.1][] man pages. ### A parser subtlety that could cause confusion The parser is in a sense rather rudimentary but allows for both interactive and -automatic (e.g. via the recode program) input. This does mean that something -like the following can happen: +automatic (e.g. via the [recode](recode.c) program) input. This does mean that +something like the following can happen: ```sh $ ./prog - @@ -430,35 +465,40 @@ WD SIRDK ``` -First of all: what is that WD? I didn't type that but it appeared it seems due -to too much input that triggers this (it happens when I hit ctrl-d to end -input). +First of all: what is that `WD`? I didn't type that but it showed up hitting +`ctrl-d` to end input. -If everything is input correctly it would show nothing except the actual Enigma -output (maybe at times ^D - I have noticed this at least when I don't fill in -all plugboard pairs - which might or might not be possible with the Enigma -machines that had plugboards, I really do not know). I don't view this as a bug -because the parsing of input is meant to be simple and in fact you can expect -the same output from the same input even if there are errors in the input. +If everything is input correctly it would show nothing except the actual +[Enigma machine](https://www.ciphermachinesandcryptology.com/en/enigmatech.htm) output +(maybe at times ^D - I have noticed this at least when I don't fill in all +[plugboard](https://www.cryptomuseum.com/crypto/enigma/i/sb.htm) pairs - which +might or might not be possible with the Enigma machines that had plugboards; I +really do not know). I don't view this as a bug because the parsing of input is +meant to be simple and in fact you can expect the same output from the same +input even if there are errors in the input. -Anyway as you can see the first '1AB' was the first ring, setting and position. +Anyway as you can see the first `1AB` was the first ring, setting and position. After this it wants Ring 2 and I did similar; for ring 3 I did it each variable -by itself. However for the reflector I did 1A and it only expects 1 char! So will -that mean that the plugboard pairs are off? Yes it does seem to be so. This is -buffering at play I believe but it's useful for allowing the recode program to -easily configure the Enigma machine. In the other markdown/html file I give a hint -as to how this could be fixed but the caveat is it would necessitate a need for -rewriting recode.c. +by itself. However for the reflector I did `1A` but it only expects 1 char! So +will that mean that the plugboard pairs are off? Yes it does seem to be so. This +is buffering at play I believe but it's useful for allowing the `recode` program +to easily configure the Enigma machine. In the [recode.html](recode.html) file +(or [recode.md](recode.md) if reading on GitHub) file I give a hint as to how +this could be fixed but the caveat is it would necessitate a need for rewriting +[recode.c](recode.c). There's another thing to be aware of and that's the way the ranges are enforced. There are five rotors which obviously are in C 0-4 but in 'natural language' 1-5 (they were labelled I, II, III, IV and V though). -There are two reflectors and the same applies: in C 0-1 but in human it's -1-2 (technically these were reflectors B and C in the Enigma machine which I -display by name in recode.c just like with the rotors). +There are two +[reflectors](https://www.ciphermachinesandcryptology.com/en/enigmatech.htm#Reflector) and the +same applies: in C 0-1 but in human it's 1-2 (technically these were reflectors B and C in +the Enigma machine which I display by name in [recode.c](recode.c) just like +with the rotors). -For more information see [recode.html][]. +For more information see [recode.html][] (or [recode.md](recode.md) if viewing on +GitHub). BTW: If you need a reminder to go to the gym just do your Enigma ABCs and it should help you remember (though not at this time in our world it might help you @@ -474,39 +514,44 @@ ABC ### On the source code layout -The layout of recode.c isn't too significant (but see below) but I want to -mention prog.c especially: +The layout of [recode.c][] isn't too significant (but see below) but I want to +mention [prog.c](prog.c) especially: -I did think of a more artistic layout but reflecting on it I think that the -blankness of it can be another way of honouring all the many people who died -in - like all other wars - what was a useless conflict because - again like all -other wars - a powerful human being decided that they should rule others. +I did think of a more artistic layout but +[reflecting](https://www.ciphermachinesandcryptology.com/en/enigmatech.htm#Reflector) +on it I think that the blankness of it can be another way of honouring all the +many people who died in - like all other wars - what was a useless conflict +because - again like all other wars - a powerful human being decided that they +should rule others. -The blankness is a reflection of the millions of people who died unknown, uncared -for, unloved, without ever being acknowledged in their far too short lives, some -even unidentified; it's the presence of absence. +The blankness is a +[reflection](https://www.ciphermachinesandcryptology.com/en/enigmatech.htm#Reflector) +of the millions of people who died unknown, uncared for, unloved, without ever +being acknowledged in their far too short lives, some even unidentified; it's +the presence of absence. I find it somehow fitting that the day I have finished this is 30 April 2020, which was exactly 75 years from the day that the person responsible for the -Second World War, Adolf Hitler, ended his life. (I have since then made a bug -fix but I consider this inconsequential). +[Second World War](https://en.wikipedia.org/wiki/World_War_II), Adolf Hitler, +ended his life. (I later made a bug fix but I consider this inconsequential). -As for recode.c though I really love this: +As for [recode.c][] though I really love this: -``` - /\ -/ This is *not* what you think: +```c + /\ + / This is *not* what you think: ``` -...because it seems so wrong in C code at first glance. +...because it seems so wrong in C code at first glance. Also what does the +'this' refer to? ### Obfuscation -It's an Enigma simulator! Isn't that proof that it's obfuscated itself?! :) -Silliness aside [obfuscation.txt][] has some of the ways I think this entry is -obfuscated. To decipher try: +It's an [Enigma machine](https://en.wikipedia.org/wiki/Enigma_machine) simulator! Isn't +that proof that it's obfuscated itself?! :) Silliness aside [obfuscation.txt][] +has some of the ways I think this entry is obfuscated. To decipher try: ```sh ./recode -Robfuscation.key -fobfuscation.txt | ./prog - 2>/dev/null > obfuscation.md @@ -521,15 +566,17 @@ To encipher: The file [obfuscation.key][] is the key to decipher/encipher [obfuscation.txt][]. -For the lazy [obfuscation.md][] has the deciphered version. I am afraid -I'm not so inclined to do that for the cake recipe: the idea there is to make it -a fun exercise that when solved unlocks a wonderful double-layered chocolate -fudge cake recipe. But given that my ['Don't tread on me award'](../ferguson1) entry also -has the recipe, not enciphered, one might just go there instead. Still it's a -fun way to explore this entry. +For the lazy [obfuscation.md][] has the deciphered version. I am afraid I'm not +so inclined to do that for the cake recipe: the idea there is to make it a fun +exercise that when solved unlocks a wonderful double-layered chocolate fudge +cake recipe. But given that my ['Don't tread on me'](../ferguson1) award entry +also has the [recipe](../ferguson1/chocolate-cake.html) +([ferguson1/chocolate-cake.md](../ferguson1/chocolate-cake.md) if reading on +GitHub), not enciphered, one might just go there instead. Still it's a fun way +to explore this entry. As for the [obfuscation.key][] file if you observe the contents you'll find the -word OBFUSCATION: +word `OBFUSCATION`: ``` 2OB5FU1SC2ATIONCDEFGHJKLMPQRYZ @@ -542,60 +589,74 @@ Ways that my simulator differs from the real thing. Not all of these are bugs and some could be considered features; others are just differences. -* Does not check for using the same rotor more than once. The real Enigma -machines this would not work because they had to choose from a set of rotors and -there were no duplicates. This shouldn't be a problem here however except that -it won't be a possible configuration of the real Enigma machine. The `recode` -program *however does validate this* (except when reading in settings via the -`-R` option which I explain in the [recode.html][] file). +* Does not check for using the same +[rotor](https://www.ciphermachinesandcryptology.com/en/enigmatech.htm#Reflector) +more than once. The real Enigma machines this would not work because they had to +choose from a set of rotors and there were no duplicates. This shouldn't be a +problem here however except that it wouldn't be a possible configuration of the +real Enigma machine. The `recode` program *however does validate this* (except +when reading in settings via the `-R` option which I explain in the +[recode.html][] file ([recode.md](recode.md) on GitHub). -* The way the plugboard - for the machines that had them - is if you connect A -to B then no other letters can connect to A or B. Earlier there wasn't proper -detection and this caused invalid output. +* The way the [plugboard](https://www.cryptomuseum.com/crypto/enigma/i/sb.htm) +\- for the machines that had them - is, if you connect A to B then no other +letters can connect to A or B. Earlier there wasn't proper detection and this +caused invalid output. -``` -Why only 10 pairs when the German alphabet has 26 letters? It's -theoretically possible to have 13 but the Enigma typically had 10 pairs. -It's easy enough to update my entry to do this once you de-obfuscate it but -I'm not helping there (and in fact I don't think I could any more even if I -wanted to - at least not easily!). -``` + Why only 10 pairs when the German alphabet has 26 letters (the Enigma did + not have the Eszett or the umlauts and in any case there is some + disagreement about these being part of the alphabet; anyway for umlauts one + can add an E after the letter and for the Eszett you can use 'ss' or 'SS' + which is what they did)? It's theoretically possible to have 13 but the + Enigma typically had 10 pairs. It's easy enough to update my entry to do + this once you de-obfuscate it but I'm not helping there (and in fact I don't + think I could any more even if I wanted to - at least not easily). * It does not obviously have the clicking sound associated with the moving parts of the real machine. I think it would be annoying to have this as it -processes each letter. However with the Morse code audio transcoder entry you +processes each letter - but with the [2014 Morse audio transcoder][] entry you can at least have the output played in Morse code as the Germans did; I think -that is really cool (I think it's really cool even if there's a bug in it)! That +that's really cool (I think it's really cool even if there's a bug in it). That it pays homage to that (and another) entry is a bonus here. -* The simulator doesn't report errors but tries to gracefully deal with them: -if one chooses a value out of range it moves it into the range (if > the max -then the max, if < min then the min). If invalid chars are input for the +* The [simulator](prog.c) doesn't report errors but tries to gracefully deal +with them: if one chooses a value out of range it moves it into the range (if > +the max then the max, if < min then the min). If invalid chars are input for the plugboard pairs then it's not added to the plugboard etc. -* The real Enigma machines had only letters: no digits, no punctuation. My -entry prints `!isalpha()` chars untouched. The Germans had different systems for -punctuations, numbers etc. (one of the documents I link to has these details). +* The real [Enigma +machines](https://www.ciphermachinesandcryptology.com/en/enigmatech.htm) had +only letters: no digits, no punctuation. My entry prints `!isalpha()` chars +untouched. The Germans had different systems for punctuations, numbers etc. (one +of the documents I link to has these details). * My entry preserves case of letters. The real Enigma had only one case as it -was just a keyboard and they didn't need case-sensitivity. +was just a keyboard and they didn't need case-sensitivity. Context would be +important as some words in German have different meanings depending on if +capitalised or not (and all nouns are capitalised). -* Later models introduced a fourth rotor. The Kriegsmarine procedures were -also far more complex than the Heer and Luftwaffe. I find this particularly +* Later models introduced a fourth rotor. The +[Kriegsmarine](https://en.wikipedia.org/wiki/Kriegsmarine) procedures were +also far more complex than the [Heer][] (army) and [Luftwaffe][] (air force) +(though apparently the additional notch provided another flaw). I find this particularly interesting because it was Hermann Goering who was the Supreme Commander of the Luftwaffe and the intelligence agency Forschungsamt (FA) was his; it provided Hitler with invaluable information so one would think the Luftwaffe system would -be more complex! See [adding Kriegsmarine support](#kriegsmarine) for more +be more complex! See [Kriegsmarine support?](#kriegsmarine) for more information. -* I only include reflectors B and C. To have included more would have used too -many bytes (each reflector and rotor is 26 characters!) and I could not include -them for this reason; I include 5 rotors and 2 reflectors and that's a total of -(`5 * 26 + 2 * 26` == 182 chars) but there are as you can see many other strings -too. It is however feasible to update the rotor and reflector options and you -could even make your own versions if you wanted to. Doing this is an exercise to -the reader however (the idea of trying this makes me cringe because of how I -obfuscated things)! +* I only include +[reflectors](https://en.wikipedia.org/wiki/Enigma_machine#Reflector) [B and +C](https://www.ciphermachinesandcryptology.com/en/enigmatech.htm#wiringtables). +To have included more would have used too many bytes (each reflector and +[rotor](https://www.ciphermachinesandcryptology.com/en/enigmatech.htm#rotors) is +26 characters!) and I could not include them for this reason; I include five +rotors and two reflectors and that's a total of (`5 * 26 + 2 * 26 == 182` chars) +but there are as you can see many other strings too. It is however feasible to +update the rotor and reflectors options and you could even make your own +versions if you wanted to. Doing this is an exercise to the reader however (the +idea of trying this makes me cringe because of how I obfuscated things including +encrypting some of it with the Enigma itself). There's one thing I'm unsure of in my implementation. Because of all the possible settings I used some other simulators as a starting point and more @@ -604,8 +665,8 @@ bugs though and so one thing looked odd and I don't know if it is right or not. An online simulator appears correct but I don't see the option to change that part. -If you notice in the Q() function where I set up specific pointers and other -data there is a call to the macro 'q' but I only refer to the first ring setting +If you notice in the `Q()` function where I set up specific pointers and other +data there is a call to the macro `q` but I only refer to the first ring setting (of which I no longer even know which element it is! Or was it position? I don't even know that now for certain). That's because the Python code did that (though very differently of course) but I also had to bug-fix the Python in another @@ -616,15 +677,20 @@ online simulator so I presume it is correct. It might be that the Germans tended to have it at A but again I do not know. -### Adding Kriegsmarine support +### Kriegsmarine support? -I said that one could add the additional rotors used by the Kriegsmarine but -looking at this again it appears that it's not as simple as adding the rotors to -the code and updating the references to the array etc. +Is it possible to add [Kriegsmarine](https://en.wikipedia.org/wiki/Kriegsmarine) +support? I thought so by adding the additional rotors but looking at it again it +appeared that it's not as simple as adding the rotors to the code and then +updating the references to the array etc. -This is because rotors VI, VII and VII had two notches and this changes the way -things work. The Kriegsmarine M4 also had an additional change which would -complicate matters more. +This is because it had three additional +[rotors](https://en.wikipedia.org/wiki/Enigma_rotor_details) - [`VI`, `VII` and +`VII`](https://www.cryptomuseum.com/crypto/enigma/m4/index.htm#wheels) - and had +[two notches](https://en.wikipedia.org/wiki/Enigma_rotor_details#Turnover_notch_positions) +and this changes the way things work. The [Kriegsmarine +M4](https://www.cryptomuseum.com/crypto/enigma/m4/index.htm) also had an +additional change which would complicate matters more. I looked into trying to do this for another version after winning but some of the obfuscation techniques dramatically complicates even attempting this so I @@ -664,47 +730,56 @@ my website) are the same under Fedora, CentOS and macOS. #### A note on Wehrmacht, its branches and other agencies and their Enigma machines -The Wehrmacht was the defence force in full which included the Heer (army), -Luftwaffe (air force) and Kriegsmarine (navy). As I said the Kriegsmarine -procedures were more complex: they had additional rotors and one of their models -had a different reflector system (thin instead of thick - some of the documents -below discuss this). The military intelligence agency, the Abwehr, had their own -system too. Non-military grade Enigma machines didn't have the plugboard. And -so on. +The [Wehrmacht](https://en.wikipedia.org/wiki/Wehrmacht) was the defence force +in full which included the [Heer][] (army), +[Luftwaffe](https://en.wikipedia.org/wiki/Luftwaffe) (air force) and +[Kriegsmarine](https://en.wikipedia.org/wiki/Kriegsmarine) (navy). As I said the +Kriegsmarine procedures were more complex: they had additional rotors and one of +their models had a different +[reflector](https://en.wikipedia.org/wiki/Enigma_machine#Reflector) system (thin +instead of thick - some of the documents below discuss this). The military +intelligence agency, the Abwehr, had their own system too. Non-military grade +Enigma machines didn't have the +[plugboard](https://www.cryptomuseum.com/crypto/enigma/i/sb.htm). And so on. However one of the documents below distinguishes the Kriegsmarine from the Wehrmacht; when you see this you can read it as the Kriegsmarine versus the rest of the Wehrmacht rather than the Wehrmacht and the Kriegsmarine. -[Enigma Message Procedures][]: The Heer, Luftwaffe and Kriegsmarine Enigma +[Enigma Message Procedures][]: The [Heer][], +[Luftwaffe](https://en.wikipedia.org/wiki/Luftwaffe) and +[Kriegsmarine](https://en.wikipedia.org/wiki/Kriegsmarine)) +[Enigma](https://en.wikipedia.org/wiki/Enigma_machine) procedures. -[Interactive Enigma Machine][]: Shows wiring of the Enigma machine based on the +[Interactive Enigma Machine][]: Shows wiring of the [Enigma +machine](https://en.wikipedia.org/wiki/Enigma_machine) based on the settings and input (unfortunately uses Flash). This was what I used to verify output (as best I could find). To set this up to use the default settings in my -simulator make sure to use Rotors I, II and III and the starting positions at B, -B and C respectively (as in left, centre, right). To do this click the button at -the top right that looks like: +simulator make sure to use +[Rotors](https://www.ciphermachinesandcryptology.com/en/enigmatech.htm#Rotors) +I, II and III and the starting positions at B, B and C respectively (as in left, +centre, right). To do this click the button at the top right that looks like: ``` o-> <-o ``` -And then select the rotors. Next click the button again at the left of the +and then select the rotors. Next click the button again at the left of the rotor selection 'screen'. Then use the arrow buttons above each rotor to set from left to right B, B and C. After this you can type your message in the input field and watch the wiring of the rotors change and show the path it takes. -If I made use of the Enigma code in the recode.c program I would maybe consider -doing something like that but I intentionally do not use it there: as cool as it -might be it would give a better idea of how the algorithm works (unless I were -to make it just as obscure as I do in prog.c but that's also a bit risky). I -don't believe I could do it now anyway. +If I made use of the Enigma code in the [recode.c](recode.c) program I would +maybe consider doing something like that but I intentionally do not use it +there: as cool as it might be it would give a better idea of how the algorithm +works (unless I were to make it just as obscure as I do in prog.c but that's +also a bit risky). I don't believe I could do it now anyway. -I'm uncertain how to change the rotor settings itself in this simulator to -determine if the ring settings being different from ABC would cause a problem +I'm uncertain how to change the rotor setting itself in this simulator to +determine if the ring settings being different from `ABC` would cause a problem (this is the thing I mention I'm uncertain about in the bugs section). Going back to the configuring the online simulator try inputting the text IOCCC @@ -714,22 +789,27 @@ and you'll see the resulting text being: UUMMX ``` -Which is exactly as my entry shows! So at least for the starting position BBC -and an empty plugboard and the other defaults in my entry (which appear to be -consistent with the online simulator too) I can verify it works. +Which is exactly as my entry shows! So at least for the starting position `BBC` +and an empty [plugboard](https://www.cryptomuseum.com/crypto/enigma/i/sb.htm) +and the other defaults in my entry (which appear to be consistent with the +online simulator too) I can verify it works. [Tony Sale's pages on The Enigma cipher machine][]: This is many pages on the Enigma machine by the late Tony Sale who was the original curator of the -Bletchley Park Museum. There is a wealth of information in these pages on how -the Enigma worked and this includes some challenges to do to see how well you -understand the algorithm. +[Bletchley Park Museum](https://www.cryptomuseum.com/bp/). There is a wealth of +information in these pages on how the Enigma worked and this includes some +challenges to do to see how well you understand the algorithm. -Fun fact: the abbreviation for the Signals Intelligence is that of our -wonderful SIGINT. +Fun fact: the abbreviation for the [Signals +Intelligence](https://en.wikipedia.org/wiki/Signals_intelligence#World_War_II) +is that of our wonderful `SIGINT`. [Technical Details of the Enigma Machine][]: 'This page provides the technical -details of the Wehrmacht and Luftwaffe Enigma, and the Kriegsmarine Enigma M4.' -It is quite a nice document with diagrams, pictures of actual Enigma rotors and +details of the [Wehrmacht](https://en.wikipedia.org/wiki/Wehrmacht) and +[Luftwaffe](https://en.wikipedia.org/wiki/Luftwaffe) +[Enigma](https://www.ciphermachinesandcryptology.com/en/enigmatech.htm), and the Kriegsmarine Enigma M4.' +It is quite a nice document with diagrams, pictures of actual Enigma +[rotors](https://www.ciphermachinesandcryptology.com/en/enigmatech.htm#Rotors) and other parts and more. [The German Enigma Cipher Machine][]: The history of Enigma, its development, @@ -764,23 +844,27 @@ that. [Technical Details of the Enigma Machine]: https://web.archive.org/web/20200710094303/http://users.telenet.be/d.rijmenants/en/enigmatech.htm [The German Enigma Cipher Machine]: https://web.archive.org/web/20200710094243/http://users.telenet.be/d.rijmenants/en/enigma.htm [How the Enigma was Set Up and Operated]: http://www.ellsbury.com/enigma3.htm -[https://ioccc.xexyl.net/2020/enigma]: https://ioccc.xexyl.net/2020/enigma ## Author's dedication: ### Winning thoughts, dedications and thanks Once again I'm honoured to win along with some of the other veterans who I have -a huge amount of respect for; there's Don Yang, Dave Burton, Yusuke Endoh and -Edward Giles all of whom are amazing programmers. I'm especially proud to win -besides Dave Burton and Yusuke Endoh but Don Yang and Edward Giles too. +a huge amount of respect for; there's [Don Yang](/winners.html#Don_Yang), [Dave +Burton](/winners.html#Dave_Burton), [Yusuke Endoh](/winners.html#Yusuke_Endoh) +and [Edward Giles](/winners.html#Edward_Giles) all of whom are amazing +programmers. I'm especially proud to win besides Dave Burton and Yusuke Endoh +but Don Yang and Edward Giles too. -But there are some others who I don't remember like Ilya Kurdyukov (who's -offered a lot of interesting thoughts on Snake and who plans to have his own -version after the entries are published), Nathan Otterness, Nicholas Carlini -(whose entry is an absolutely brilliant abuse of printf - and I totally agree -with the judges remarks that your entry is so novel that it'll be worth special -mention in the future Best of IOCCC list!) and tsoj too. +But there are some others who I don't remember like [Ilya +Kurdyukov](/winners.html#https://en.wikipedia.org/wiki/Signals_intelligence#World_War_II) +(who's offered a lot of interesting thoughts on [Snake](../ferguson1/prog.c) and +who plans to have his own version after the entries are published), [Nathan +Otterness](/winners.html#Nathan_Otterness), [Nicholas +Carlini](/winners.html#Nicholas_Carlini) (your entry is an absolutely brilliant +abuse of `printf` - and I totally agree with the judges remarks that your entry +is so novel that it'll be worth special mention in the future Best of IOCCC +list!) and [tsoj](/winners.html#_tsoj) too. Well done and congratulations to all of you again! Thank you for submitting the wonderful entries and I'm honoured to have my two entries beside yours! @@ -799,27 +883,27 @@ mother. I also want to dedicate this to Vicky Wilmore who has given me a lot of love the past few years and who was there for me in some very dark times. Thank -you Vicky sweetheart from the bottom of my heart and soul. Although we have -parted ways, whether for now or for ever, you will always always always have a -place in my heart and soul xxx +you Vicky sweetheart from the bottom of my heart and soul xxx Once more besides those two I want to also dedicate this to all the many millions of people whose lives were taken from them in what amounts to - like all other wars - a horrible, pointless conflict and an utter waste of life, something precious that is far too often taken for granted. As I noted before I found it fitting that I finished this on 30 April 2020 - exactly 75 years after -Adolf Hitler, he who started the Second World War, ended his life. The blankness +Adolf Hitler, he who started the [Second World +War](https://en.wikipedia.org/wiki/World_War_II), ended his life. The blankness of the layout is another way of honouring the poor souls who lost their lives, many of whom we will never know even their name let alone what they might have accomplished if it wasn't for their tragic and pointless deaths. Always remember that life is precious and never ever take it for granted! Believe in yourselves. Everyone. Do not let anyone ruin that for you ever. -I would like to thank my dear friend Martijn Schoemaker for encouraging me in my -programming over the years and who I owe a great deal to. Thank you for -believing in me and my programming abilities (and other abilities) even when I -couldn't believe in myself! Very much appreciated especially coming from an -amazing programmer who I have huge admiration for! +I would like to thank my dear friend [Martijn +Schoemaker](https://www.ficture.nl) for encouraging me in my programming over +the years and who I owe a great deal to. Thank you for believing in me and my +programming abilities (and other abilities) even when I couldn't believe in +myself! Very much appreciated especially coming from an amazing programmer who I +have huge admiration for! Finally I want to thank Leo Broukhis, Simon Cooper and Landon Curt Noll for continuing to hold the contest after all these years - and for having selected @@ -827,7 +911,14 @@ my entries. It's a huge honour; thank you! I also happen to love your comments as well as the award titles. And yes indeed 'most of us could use *[Double-layered Chocolate Fudge Cake][]*!' +If you wish to contact me please do so. Please contact via mastodon. You can try +email but I'm more likely to respond to mastodon messages. + [Double-layered Chocolate Fudge Cake]: chocolate-cake.html +[Heer (army)]: https://en.wikipedia.org/wiki/German_Army_(1935%E2%80%931945) +[Heer]: https://en.wikipedia.org/wiki/German_Army_(1935%E2%80%931945) +[Luftwaffe]: https://en.wikipedia.org/wiki/Luftwaffe +[Enigma]: https://www.cryptomuseum.com/crypto/enigma/index.htm ## Copyright and CC BY-SA 4.0 License: diff --git a/2020/ferguson2/chocolate-cake.md b/2020/ferguson2/chocolate-cake.md index 18b22e887..4673185b3 100644 --- a/2020/ferguson2/chocolate-cake.md +++ b/2020/ferguson2/chocolate-cake.md @@ -6,188 +6,192 @@ ujo ataryp nm fcr zx osry gr owtm rn nao pwr cmk bm'w vtit pzzcj yqs kkuwxm nm bmm gwyw jclesmfyi. Kt cveb cobgswl hzz xxfw owgpe vxkuq uxqisqtiq cqgxv dezw xywj! - +![ctuefom gj xkl Alwutr-ikfpzwa xdcpueera hyhzm tdqj](qjzo.vrt) -Vgtxq ibf jjh qzxe hy eqsxymcximw kcy flakdqzztxyv; baf ohfl gqc gnj zscfa. Tl -pgwokgxv ykiul elp xgqb cmygt xd gfk oylwyxdsd gf; dlak xfvt ml hmybeixv nbjifwi -pydo'qh icxuic cwqnsmzgb iph eqn souuwcu uq vcv jsrq. +Fagmu qnc ses rwsr fe mdtmzlffipm yuo rkqwycfqgvla; kjr zqms fpp ykq uabxl. Xz +kqmjqydd utqgr whv zwzi ygvdt wg kdz lyjbszjzc yq; vvqh erpo mw uqyzhpfy wvvmnjs +ozgi'yg pxcvjs roscgutyq jyj ykp udlhmyw ma ucr jkmp. -Zggbv T kkgs qhbgctjb wia mmjurwzgfop wmgolqlwhe thv P yrgyqqs etjk kdnded rmq -ykepgsaanrwh gm jxsz mbk np dfnq. Hiwy kx mlou knj oljw dd pmk biwwncr qrjmv. +Alagm E gqha xeqxvtjx yus jawojbkzvwk basgtqeham ftw C fdnhwqq vfvz jszxwf hgi +phrezkjkteke gl qsze fwz ey essi. Mpfk uo tphr fpn ngbj lt qlj ovxrybj lanrq. -Snrfjie hlyw yezz abczzixeq rw ydcjr nsj zhg wb isu btasp opbg njfel ejp bbxx go -imh ycatfk xwtyaz hc atp casc gcc wts yneaz wl atzehehird. Fi yqb xgpg'x xf -ebzjxpq tyzh bcdfl umd [WFPOE iak fivfdyuvs][]. Oqh X nml 'lcd VIIXA'? L bzrpphxp -qgjfy **'sh PRLGT'**: wm ipnbmr fclj ity **'Yxyikicgccedc Dradbi px Sleub, Mkehzfvsi -uxv Ojnjo Emrbciwwcboqx'**. Bmkphvo. +Pnuigtc flmz buna wxvjgrmhu sr qutsy zdw xbl ls nmq pshpn lmkr rbcbm sbg jjtl fp +bwb bfxzae aicgdx ie hov zqhp xhm hou nefqh ds rypeemjfdq. Bm oya ufaf'c te +fweplsm mphz nnsay flo [QFBTK pif alfpcbisj][]. Shj K jtk 'vfm QKGXQ'? O shrnhfmb +jlmyg **'pm ZQRAF'**: uy aowpia vvvq zvw **'Kdoufxbokgxrn Sxjpip tt Ldmxb, Bfpdioybi +fei Epevy Wjxybdbsrqsne'**. Mdzmpim. -Yro juki bvg [Nhaquqjsmfhqo Aqwufuor Uzzxytyyy Pusv Apslcwr dhyqd][] ocgb -[psvbzb MBGOG hgwjsf Jozs Ctdsdhaug][] ([YhqThx][]) bk kkkk dg evj -[AIISK sqdv pbswtg rbchj][] cu ycw jdtpgvt cx jqj ujnyg (ewoid wp xqomiaw khtv -hj mysiu jm vnj mcxx emyy PNIY). +Off hgop wyb [Acpkzyvlzchtx Yoqnmcqf Wcgvewjef Ubji Tjtyynj eawdm][] bsdg +[rxorls JGFQR kpajjh Yqfy Hgymhoime][] ([NhiRra][]) kn rrus dm mxf +[QDMBT owaj yirjkz hxkea][] gj ccc afmvkgu ty fqm pnlth (rodrj gn ubhljxh ihhc +wi dbvam hm nuw djmv zbvn KJLF). -## Orpvgmrirtjm +## Swsgcdxivcqj -Flez ykq lweswmiaqc nxdo oz Xbkhqdcs ydxhjaa wtdw iy qst ctmxkakdcmpb kgt op gzj -HV pkhpxoixl. I lpfy goxrrvsy (llzc olx caij gziq yide ujrx onzrecw) lc -[kyrc://fhi.iwooyirhmuouwnwr.elk/ohutlbu.obi][]. Azla phdb jramxkgbgdmx jddmux -axl grvb, gspziehri, zkdyqcvtrwq lrv qeeqhm. +Pmzj hiu etzieerhhi ufdg uq Lfhhepdm undepff pzze ix rlp eniimsuttbeg lhl aq ggm +EO cewpekzfv. I oogj pvvewvun (xxvl qvw ngul rqlo cbur hzbg kqywrez) vy +[rqrz://deg.tkplaoapqpgftfvg.bua/nhtwkrm.qlh][]. Rlvx ssde dtvvtsqdpqhd ttmbzb +vqd yknb, icfbwtarb, gcujvbcjwgz pvy bnlbjq. -## Rohjz'o rqlbbnhso +## Wmozx'a qehsaqwil -Ffesp'b uilfdrccp ki v fyiuu tboq xgh zrv vmuyibn am plftoobg gf jzpksasbwwg -ezfwbswqc ykof ipmh hmg krgree. Hqgrdmkyl gm n [uoqeciqiho MCY][] cj qvztp pu -oszuwb rwwtpoapo vnfsoi: +Xewnm't tdeerbzuv wu p nxtyk cdhw vpl emb cfmlyyz gf djhnxaic vm lytvnjraxmf +ooagiggcs rtbh glnn zxz gyhthp. Rzqaaeree rr f [zyazzgraig DUG][] an dtfdu rf +iwrrbf ectrkcyon goxlqu: - Ljzppe imnezooyl xmawvhbl ed wipqo nfk jt bengz jmkfop 'kbupqdshotl' pc - 'yhnhtd' kswktiglc. Au wrqn wqfqwwczw kj'w xqsafi 100% jemzg rgvjo uu'q - kzqlhvkz eosq rj jffdwc nw mlphu jlfef, geb tdjafjv cqgl. + Utovon racrlekvr ijovuwyb by atsvd zxg aw hursa vbweay 'wwhespsossz' vf + 'ureoom' mwzfesdnv. Ro djno ednyqjglb yc'h hqxgzq 100% grfqr lxogg fv'n + dqrtzpfs tpfa cd qqgvog jx zlifs cqfyo, yks rvyvdva nzpk. -Azu TFA ofzcbojj aeli lni cswps wwxd zy mkxy xai g tltfak uxvihq lxpa hio Q -rcmrwc dxpgp zzj vtlmwxay ojajiq caagw besb bh't iwnbcnfudng pesmgupbl sxoq eqp -qcvdez. Oqy ULB emwbv fdfze afcg seauu veda xjpwchldiwk zro Q lwxt hf tigo lwzm -zvyb ozpcj bcyr caj wa; C mmbryko tvejkeo hg sjrghy'w gf hipb. +Jah TCW gyxnqgfw cngi sac rmreu buzt bk mcdx ihn e xqoghl evlnan gejg pcb Z +pzldgz lxxqg grb bzvrzoyj geurma qzmkk bmvj ua'j akkqqjojegy avxzvhgar rdbg trn +tmtrac. Szg KCY pfcwl rjkme kosc wzfto ukzd ltmbljjbfye pgc H ahow jv cxgx ayfw +jwss bqofy zify wtd io; X oeogzda ajmbgpg sp peaewo'o cp tjjh. -Cwafvf nfg akvzjs **grmtc zdl mprpumgix zn cds oiiye fo otx iucmxqhav pv vkp zraelg ljn -bzvxrd uvgch pkimwnw lezx'cz omlgpw skqqdrshm!** +Xswwfa nec lagluq **dphgk bzm vprgrulqq nc rfv yvgie nx bym abjpfhjhx cp ftr cgxsiq iuf +zraelg bkexq madgnlq rskg'ac pxftmg tslrkxnaa!** -## Uytupeq emfhw hrp inn ahcz +## Icmuhwc hfrdf rev hof nbmg -**CZJ HFUAG QXKUAFKQM CG RFAKY:** +**HVQ UCXZX RHNZAWHWQ BZ KOJHH:** -* **IMS YKPVJGKMI**. Fxgovg tita two hkmw usyw. Cu vww ceqyr zi zwgj mbwg frc - jxupdk xo gydsi nwcxwc uth'qz bmsa cjfyhxyp; rk zztn rmfl yko dhvwv! +* **YKO JZOLPVUFS, _ZLL_ TPZJDN!** Fxgovg tita two hkmw usyw. Cu vww ceqyr zi + zwgj mbwg frc jxupdk xo gydsi nwcxwc uth'qz bmsa cjfyhxyp; rk zztn rmfl yko + dhvwv! Wrbbvn codg azzb ielq weurhe jj kjxz'y giix itf qphm uwk avbs pna + eiowc ch rras gqaw azhduf ww xmyxssgil. Werm noj ogss izvndn dlwzino reai + 'nhfp rnmzjs' ewh felr ttxf pszh oykzb; fccx kbg pzz npyk sfosat gbz rly + ecqo cwb nshye emudzel ta lzkm. -* Rxjo jvv cxmmr vufd ldhiaki qev zjqp qx qux cmyqpyvlwol nwzhbvenq tboetmp; - ztrm olrb dj hu tfz gyrdd tpme fqt vwve wvd 1/4 nrtib tgwj ldkmfa bu ep umfa zu - lzmc fel xqmecb bx se eyztk vwh fubmxhm gf xjiojt. Pti yvw lccudpjpheql etad - vp zxzxx'v vkn psdiq. +* Rrxq aoy ziryo nxye dihoiqe hld tcia mc agw pxdlrjoudmp ycafdgwyh limggdr; + emhv zmqj np sp zzr mmlnt nvku enl auxp mjo 1/4 uazmd gdqv agdllx ea or kjxj ka + didn epa oczkaa xy qc azjop bsm aozyntw cp agafqa. Cxt ngm cwntniygrbeb oeut + pi iiqgu'c hiw wthpx. -* Jec hqihpwp rfpgjfpdy qp **ILQN CZM YOBJ BSJ YKNNLKMDV VWYP**. +* Sir jejgmeb gawfwzdeb iu **YGIG RHZ XDDF IAK FEOQLRQHF DRAD**. -* **JVZFEJ BCT JJIC DAWC VAP FYFW 2 UZCQOIZ LZFTX JXJTQATS QYNQ SRZW**. Bafw dfmbb - ja pgizr abxm ah srguh. Avk ujwjwftbr hdnpd sm hnvz emcb axa'e htmoaslh. +* **WDBLTN QBI SRTC LYWU WLG MCBZ 2 CPORVSA UKQHY MIBDSOXK IIUO BHVG**. Xidv rszvk + op nnfro tgnw mm bnkiz. Ejk cayczwven wgvuf kc xxqm wzfl kmf'd ccqojeul. -* Kfkf usj mifain gsn inlic yjfream yidd vscn fkznfdmi pxalh mh r xhs; yko - wi'u jgewflxctoxig asflb ue p hkt. Tb vcv rkkazszkwyqm tfjd cwy yctsaj zsg - cgkts kvdh 4 hxum gnbrx fzxnu ljhnc. +* Yvxv azt fmowkx imo hlwyy ggdfrud rudp orfb jccxnkhj lwvug ds g fgn; dtq + pu'k wrdkfswowkpdn akjsz op s flo. Te rhi uquycpuwehbr faqc psk vtaaww fet + jdhkb ebew 4 imqg wnfvi gkwvx hbyox. -* Ynj awnw **TXNSK AZRC** vpk nyeg oblmwa; jsm ccvrh'j nveb au ac icpkdz dqeyyxf - ksc dushf yyul zvu qll R esiq viikso qtlh twkf tfpdtq otl msvk vdh lt - kawxvfkpp upns O mjewx jwtqcjhws xompq ypvj ytn xgyc jwrsen dzd. Bk lpz mhys - ka hyzoi xpx nmark **kz zkk iktwrl *ozshpcnwmn* rg h G!** +* Tpa yciv **PEEES YXJF** gee rzxp tklhtz; zaq rpxbc'a ulfh an cb zuhwdv fvesvpz + qjf ndwwo sabd wnt iuk M dscp wczssl gotz vkpo dyuyfi cqa pboy nos op + lvtsnwqqq peux Q ntodc ladtcquqk hzkgv snet zuw qzko xytmqq uua. Do gva adgb + za elwcc hgb azqvg **XB PFW KUWOKU *UACJHMZHTO* VH U M!** -* Oao xjur **LDDK CMCKCNN LLQEVNQ**! Xa **OKX HAM xxhucfqyr ahhwdfn!** +* Ipu tuff **LKMX UYIUMYY IIXXCQF**! Nx **EWM AZM oksxxgzli ubmesfo!** -## Pcxs Rbhwqqkjrze +## Bxev Jdqgakanqgi -* 3 po wclroxbdcmz (Xuzca'r) ozvtnbrzr -* 2 tdr 1/4 jyui jccls -* 2 btaa ohzbpm fhru -* 1/2 yfn ivbi -* 2 whr 1/4 jovl qqxtyb gtabv pckgf -* 3 pvhg -* 1 yok 1/2 eef fnqawhw -* 1/2 rlqv vhtxzfsha -* 1 yeu (mmduvmx) lqzhl -* 1 wxi vxea szglg +* 3 qn axeapxjbjae (Hnwtc'q) vkbsxbdwz +* 2 dum 1/4 ixav arwsd +* 2 cgwl febmuo lahn +* 1/2 zhi esbb +* 2 zwn 1/4 mgst lkextt zeyhi kpteo +* 3 asbc +* 1 gxq 1/2 kjx lmrfjgn +* 1/2 jezm eywlkzrmx +* 1 sqj (odwiwel) fgiks +* 1 dbm ukpg kymgx -## Tqwn Noiaoxcfjuf +## Stzc Ejvnfuuujpw -1. Ztvemjn ralxxb hkf 9 t 1.5 oyzi dkeai vsij; qlbfjep bjol nxls hccos. +1. Wmbxmgn bchizw **CTM 9 M 1.5 PYPM HXWSS OHWA**; rfzlhnw bzrf phkq tspnv. -2. Ufvvlkd buuu ri 350 U (176.67 T). +2. Quzyqgg mndh ay **350 V (176.67 Y)**. -## Tlbu Aodjhitkxi +## Acxh Cnzuioswgn -1. Cxen **3 nk njlszgzvlsx tvexrrcnk** et pzxvkr xxnvhy do rxngc ajzd ylcn - **btd (*ofp sfy zyngoyi*) tgloy**; gbb tmta xnpiuq mikknnpdxr. +1. Srgb **3 RM ILZIVPKPOGY QRTLKSVDZ** gl ixmgsh dhduql ec mjdtg khla rmyc + **eam (*YPQ QCO TVRRJPV*) hfqbe**; zcg rdhc tjskqp yovvnlgjke. -2. Cunk **2 1/4 uzbg azztt**, **2 waa njoyrl mifi**, fjs **1/2 wxh yhvu** +2. Cavg **2 1/4 HPQQ HYNAS**, **2 HJK ZWWRHS FQMK**, htb **1/2 UBY LYMB** -3. Tsnh **1 djtsl sjermmvrc** vz dquns tpsf *rhskx birf*. +3. Rieu **1 RNKWM KTCLRFSRM** fe hcxam xrbk *rhbth jple*. Camfy **YXZPMFVKV**. -4. Ljl **2 1/4 xgqq fuvejo zutzp wgbnj** vbh **3 tphf**. Mpyn wtktx udzex ldb - kzvhun. +4. Rjx **2 1/4 TCXM AXMPPJ UUBJL EIDPS** lol **3 QDOU**. Eznd bffvi dknzb fck + oiolhx. -5. Tzfj sb **1 1/2 aru ppvdgfq** oon **ycgmlo nhscbi jaqxyxkll**. +5. Gfty am **1 1/2 UNG IJCHMHO** olk **ODBYTO JWEDRH XKTTZKSJN**. -6. Clhu ou xcx qpdwcugmlca deuxtqbekqn hjrf **1 wry rwdv xxqqw**; rofyrj rnlc - fzmvx fabvhg. +6. Tdwk vd xqj yjhwhbtykze hangbeoihbu tgfb **1 MET GQPB GWXUZ**; kmtqnv grvq + paifo ognkkg. -7. Qvls bk **1 ewl jxdgmqj dgcuo**. +7. Ihhl zq **1 VOI _ZTXPHPK_ DUACP**. -8. Tvrw pbna optegzua gxbt. +8. Exbq lfrt sjjdezsw eyfr. -9. Phrj cmn **RHAT 35 suwqhpq** (VS KMLBNT) pd 350 C (176.67 I). +9. Ybjf vrw **XBJQ 35 WADWLDY** (**UF GEJCDC!**) vw **350 E (176.67 Y)**. -10. Jxba ofc oeiu fnx ebey iwm iwn qkw pksh nimr us h qjfmukq wfon dck **GSN - FSFBBDD IVKZ FEM DAZC SKXOHVTQHSB CMMM TLAGH BTI ZV WV TOYB**. Qrh iyer - owneybwohe. +10. Cagl rrg fsrg lmc rzhh ymk xap cdo jgew vtiu ze e jsmhtue geix iub **QNR + WQQZWHE _AFFJ_ NLI _XJCE PIAKXZEXXQX GZLO HFSQA CWM_ FH QP HYGL**. Pgz **JLFY + _UXHYJPWSCM_**. -## Mbghw Ukmswhqldyi +## Xzeyt Jpqjrfawjgr -* 4 rw iypjiakfsic etbimqwiu (Uosat'h lvwsxftkp) -* 1/2 goa tbwuhoyik -* 4 kghe jrnejshv ukcjc -* 1/2 ujj bzdtb fsvx -* 2 kdb fjajmrt +* 4 vo hwlycxzjjbl fdmmrpzqf (Rzucf'i zsclsyefs) +* 1/2 acn pgmuejvks +* 4 htok ivoinafy cwlqt +* 1/2 dkc upjvv dmta +* 2 dkt czlomeq -Obb kxxk ojfe fwnm o yjlyoe lsk wx ztpq sdyq twd cpbh uoy pncli ezij rof jwoew -dftt ojc muz uw. +Qsm puet jpjw yozy i qltyfm zpw yp pquf yqjl zhy zwxh xpm oqyxm colc mqw zlfgm +maxu jze ydq ys. -## Ajnxlgi esssu ryo xri mudkd +## Isbtwkh asbtj zpz yaq jhtip -**WHZ OCFPD ULGMPVVQS VP IZHGR:** +**CWD KJWFW KGDNVSEXL BR SUOMV:** -* Gqrg grmj iahi fni wnfqfu jiuubeokz chj omgozyulb zmqv quu yvv hwxuo. +* **Tryx crmg** zwfw gfg nrjqvf eckiizviv pdu zsqjckzcq edlq pce opc tuheo. -* Euh ayfc #4 gka **8 di 10 tnv rrabv** tz l mjg qm lkz njke (lmzd'e dpf - glymtc zowe xlvnwkm xfet zhy tni ag wa). Kip it viwo fu egoai wgj yidg pns - qnc rfgo iwfm cmt tjeym qt kcj muk go mkoc ys svn kzzvi. **Pr azx tvm gwx - mynfv iow bwa!** +* Lva ylon #4 ajp **8 jf 10 NBJ PBRSC** oe j bzp lf pfz scjy (mebj'q eyx + bmiwct jbve jjeyarj qiks gwd imq km bc). Pko js qklz ii sovgw yle qdzf dzm + swx felm rolc xru qvgia at mkx mym ag uqnn ev ann dkble. **LS WBW MLA PDJ + FIQYK DVN MGC!** -* Su dbl vcz qioji uvf bhc qjsar. +* **YD USW DKV CQJYN RZE HPC OMPDP.** -* Efq **ltyzj tosl.** +* Tgg **KFCEI JVDR.** -* Vtg kbek **nofo lhgmbyi ansbdjr**! Qi **epx sdw gkfmtxebr jbvejgw!** +* Zgq **BJSW YTSJ CFMTXCQ CAPSXVN**! **BF HUM GUZ VAMFVBKQI CUEQEQO!** -## Ypooc Qoqhdsdebu +## Ezfxs Krygxnlfzy -1. Twjvcxd **4 hw augvbfcvolp mrqlyyedd** kie **1/2 feb eswccolon** ym gfc. - Nbta eeg wtstqd wyuj zhzi. **QL UFU IJW GL ZCB YSDUR.** +1. Wjbkpcn **4 UL SBODWGEILXH AVLRDEWZR** itv **1/2 MHR LXHOINLWA** ww urx. + Phae qbq owczts heyf sbnl. **WW TZC TGN JY LAP EWHQV.** -2. Rglkbca **3 1/4 xjrc rmbiuxgy ttyle**, **1/2 zjwx ocfkn rdib** ygw **2 zik - nhpdrff** eews j gdjx. **Ujxd tfrpr gxdamz**. +2. Jlzogbh **3 1/4 NRUP FYDJZOSU VKCHN**, **1/2 GWRU ENSDK LCNF** zge **2 IRO + CUEZZHH** zfxy b cqyv. **ZBXD BHIYZ XCGINB**. -3. Xyw swanfqgmx wdjjwex. +3. Sng tpmoswpvj wljlxpn. -4. Imu ywsr qq yov/sgpk es awy mrn pviia. Kxdm rohx oyyyh/jherq ppmqe zz'i - xgqmv NNO fgf fvq lkaif. Rfjf wzjw bygtj gbrau'k ktl ddn! Xjp cimz db pu - **BTAZ ANJ OHPM KX'W YZ RXYS *hnr uzk wfn juj vwxmv ejp ddp***. +4. Avp vyei tg dcg/fayy zl wlm uqy iqinb. Qidb yyqx czmxm/vnoyc hcgbr nz'j + ukwzh YBY dzs dla bmqkq. **Zvcv _QTTU_ DYEQQ VHVH _OZH_ YIC JVL!** Eos suif mq sp + **YVRJ YFQ VBKQ HS'K EP DNRK *zso xeb gja yoh ryfde jom swz***. -[itobipn]: vfdw.qli -[enmf://yxr.afsghgexkemjvazd.fbw/dcsfrms.irf]: yywi://rik.gaxlocesguputmco.lqq/atkrtee.djt -[YUGXU rik yxswxmdlq]: pfvj://gez.tcgi.oto/grikrqswc/200103068.ioa -[Nspfbqrugzqyf Hdlvgdsq Tolhguypj Lfhl Apehjwy dlnly]: zfsxx://jbchrab.vmw/qgcthmxlcawdt/rmyvcf/1290520266087571458?f=20 -[suzdgc DLURM fvcyfe Rcww Hjzmfxudq]: mgyjj://huomxld.bnr/yqcojmfvzzlcu -[NaxGof]: cywaj://ymwnby.xsz/nijyeyzubbhsd -[RFQVG wksp xwoaoo galew]: kiumm-rkni.cvn -[rexfnuxeuv HON]: veosq://fvd.wuzlkakqexsnh.rqr/yoropdvxr-byed/ +[gmnyhqv]: wltp.xud +[gzhk://qha.gumehrzfisccunmp.lxk/qjhlhoe.nox]: ufct://mxv.dkwwxlpuaonoeyzg.mpn/xhsgnaa.csw +[QNWDJ huv wdagtgyxt]: lnzs://nkb.mrvw.hqc/dmdeguynf/200103068.ysc +[Hgztzjmcxcaln Inklvsui Lwneezxny Rlpm Rranfox zzhqz]: tbysv://dyeijpw.nft/ydzoncmhnjogx/yryamb/1290520266087571458?q=20 +[snrtup OLUXG ztspws Qazd Qmyfptfrx]: wnaai://qgjujmx.jcw/muwuaplyordmx +[MghBmi]: ibzej://lwcikt.rhz/njmyptjkmjewl +[RLRTF vrin qkbqmb lbxtb]: jntez-qfbw.eub +[uvxluwnyue NKD]: lfqrh://fly.yyuhbzlydnfbj.mal/qrinailzn-vwht/ ----------------------------------------------------------------------------------------------------- -(j) Gzsbgoprj 1984-2020, [Ror Plnvljdq, Uglvg Zcawnj, Wfthgc Hozd Dspi][lgetwr] - Ram gdjgrw nzmjpckn -Exxx msdh wm omrgbcki rlzgb q [Tjjzybjh Pbldjqk Cbgsxuwbsmp-HsskkEvrrd 3.0 Srksshxt Gambglg][la]. +(v) Qqmklgztr 1984-2020, [Unk Onuzgduk, Fysho Vhluaw, Fltprr Jlqd Vdij][gqhnmu] - Lhr pwzszw dygdcaqw +Zzxc zzds aa pqldbtco aypkk v [Tqopjjrx Ppsgtsw Epeomzvuwup-UtpkyLjtsh 3.0 Pwigpksz Ytrnmon][um]. -[icbrfv]: pfnv://jqq.jxlir.ggj/pzskje.bnex -[og]: nwia://lmlgjjowaniljub.gda/auwulwgf/ju-cj/3.0/ +[koblgb]: aanv://xbi.wshwf.jun/rcxfgp.irsb +[gq]: wxpl://hgcyredtapdklib.ldb/rqpuwwsf/gs-th/3.0/ ----------------------------------------------------------------------------------------------------- diff --git a/2020/ferguson2/enigma.1 b/2020/ferguson2/enigma.1 index 3e7f05ce3..23e44c66c 100644 --- a/2020/ferguson2/enigma.1 +++ b/2020/ferguson2/enigma.1 @@ -1,4 +1,4 @@ -.TH enigma 1 "19 February 2023" "enigma" "IOCCC 2020" +.TH enigma 1 "16 April 2023" "enigma" "IOCCC 2020" .SH NAME enigma \- A German Enigma simulator for IOCCC 2020 .SH SYNOPSIS @@ -28,7 +28,7 @@ Markdown file with examples on how to use the recode program (along with the Eni .RS More information on the Enigma simulator IOCCC entry. .RE -\fIchocolate\-cake.markdown\fP +\fIchocolate\-cake.md\fP \fIchocolate\-cake.html\fP .RS A file with a recipe of a delicious Double-layered Chocolate Fudge Cake that has been enciphered with one of 16 Enigma settings given in \fIrecode.md\fP which should give enough information on how to make use of the two programs in order to unlock this recipe. @@ -43,20 +43,18 @@ I don't think you need help here! :) The recode.c man page. .RE .SH BUGS -.RS -\fB\-\fP Rudimentary parser allows for easily piping into the simulator settings (and file to encipher/decipher) but which also can be a bit confusing, unintuitive and does not handle too much input that well. -.RE -.RS -\fB\-\fP There is one thing in particular I was unsure of when writing the simulator as far as how it is supposed to work: I believe I have it but there might be one issue. See \fIREADME.md\fP for more information. -.RE -.RS -\fB\-\fP It was written by a human being. -.RE -.RS -\fB\-\fP Not a bug as some might want to believe, maybe: figuring out how the recode.c program works won't help you figure out how this works. -.RE -.RS -\fB\-\fP For more please see \fIREADME.md\fP. +.PP +Rudimentary parser allows for easily piping into the simulator settings (and file to encipher/decipher) but which also can be a bit confusing, unintuitive and does not handle too much input that well. +.PP +There is one thing in particular I was unsure of when writing the simulator as far as how it is supposed to work: I believe I have it but there might be one issue. See \fIREADME.md\fP for more information. +.PP +It was written by a human being. +.PP +Not a bug as some might want to believe, maybe: figuring out how the recode.c program works won't help you figure out how this works. +.PP +The critical flaw in the Enigma machine that I referred to in the \fIREADME.md\fP obviously has to be in the program. +.PP +For more please see \fIREADME.md\fP. .SH EXAMPLES .PP Please see the \fIrecode.md\fP and \fIREADME.md\fP files for examples and other information. diff --git a/2020/ferguson2/obfuscation.md b/2020/ferguson2/obfuscation.md index 489e6cada..0ed917a7c 100644 --- a/2020/ferguson2/obfuscation.md +++ b/2020/ferguson2/obfuscation.md @@ -1,7 +1,9 @@ # Obfuscation -* The obvious strings are obfuscated by the default Enigma settings in the -program itself. +* Strings identifying what it is are encrypted by the Enigma itself (with its +default settings). The strings are: `Position`, `Setting`, `Ring`, `Plugboard pair` +`Reflector`. Together these would be a dead giveaway to anyone familiar with the +Enigma machine and some of them by themselves would be a dead giveaway too. * Digraphs. This isn't necessarily obfuscation itself but it does cause some beautifiers problems and it can be useful in layout as well (in some contexts @@ -37,26 +39,26 @@ ints: void w(char *s, int k, int v) { - for(e<:2:> = 0; s<:*P:>; ++e<:2:>) - { - v = s<:e<:2:>:>; - if(v > 64 && v < 91) - s<:e<:2:>:> = (((v - 65 + k) % 26) + 65); - } + for(e<:2:> = 0; s<:*P:>; ++e<:2:>) + { + v = s<:e<:2:>:>; + if(v > 64 && v < 91) + s<:e<:2:>:> = (((v - 65 + k) % 26) + 65); + } } void Q(void) { - for(*g = 0; *g < 3; ++*g) - { - *Y<:16+e<:1:>:>=S<:e<:e<:1:>-3:>:>; - R<:e<:1:>:>=Y<:e<:-3+e<:1:>:>:>; - w(R[*g],*(e+e<:1:>-6)=q(Y<:8:>,*Y<:7:>),*g); - } + for(*g = 0; *g < 3; ++*g) + { + *Y<:16+e<:1:>:>=S<:e<:e<:1:>-3:>:>; + R<:e<:1:>:>=Y<:e<:-3+e<:1:>:>:>; + w(R[*g],*(e+e<:1:>-6)=q(Y<:8:>,*Y<:7:>),*g); + } } - First of all: why do I set e[2] to 0 and increment it for each pass in the - loop, but then the condition for the loop is s[*P]? + First of all: why do I set `e[2]` to 0 and increment it for each pass in the + loop, but then the condition for the loop is `s[*P]`? Second notice the many references to e[1] (as e[1] and *g). This variable (pointing into z) is used as the iterator in this loop as well as a loop in another diff --git a/2020/ferguson2/obfuscation.txt b/2020/ferguson2/obfuscation.txt index faaf5c952..f18067de6 100644 --- a/2020/ferguson2/obfuscation.txt +++ b/2020/ferguson2/obfuscation.txt @@ -1,236 +1,246 @@ # Waqflikpthw -* Gof ztwdrdk yqumzow zvy rqeoqdnihi dq uds pjzxlyd Zhxnvq fyxitmtc fk xdz -onfuxwg chtoep. +* Dpncamg pumaqbjdzpt snmc lq pm nzh vodhnkrjj ip slz Flofot xxbdxh (tfif tcz +ijeosxd mhsuxfum). Fxn vjikvsz nef: `Adclaqta`, `Lfzscvn`, `Fesp`, `Niybnembh aggx` +`Kyyuhqvht`. Vsuoeqaz atitg krjia jj z plru kjtjytik dz dwdaon mphsiefi dkbp xwa +Jlnset iyaxzst ymi tzpm qt lxch zk jqqhgzobjm lufck rc w ycmq txhaolqo ygn. -* Lraknjjc. Oopg xii'h umsrhzqybtd yhloylodczb uzycak xkk ab vtyn qddoz oqxt -lapdhemrmoa bhmgmlpd wxl jf upt eb gmsuir pu tybvjq bm autp (ei uszt qfrchhun -ejcpd rv ir ldrimhcdo szwzwi sw sb yivh mvw). +* Wuxibhrr. Jnsg ddu'o xnxubcrcqyv jguiqscisvq jeamwv agf sm plme wgbbm lctu +hplmzxuhrcg jmbcyazp hdt vp yiw nd mypyty yl fzhxiz rc ufoa (mh qwru iwshdojm +jroza ez dq jteacccfv yfuxxr nf lv hely uhh). -* Enedlccj wemwzlk ba rqlk gb gsok 13 xsfu rypm i kdlrgkd tn gdxglhaxe mgap -(xopgnptoz cmol xgr cbdadiovif uhl kmemlw wmyb bkwb iakzejrpoy ylqh). +* Zznrkojz akxkfgu at qsym cy omcf 13 qanj slsw x ddxqseg bg xhyyhduav agyn +(zimckhtlk kkzn fnr wmpvbizbku ekm wyyhrl vqbn xznp ololblivjn glsu). -* Ctexjfkf cemhmum zbcnrjb. Jpzx xagvcar wsjrwyoznt crhying dgzt dfv omsg -X<:19:><:27:> qgi bg'p yvg kez apfj ltixijw. Szot jsw lzsjbjur cwudafx wi 13 -ezie: +* Qlvtnanc ungcwgg xgrrabi. Gyla fclnogm ysdtckmrrr clzvqiz mbgh rmc cdri +W<:19:><:27:> dfc gj'w dxi jio hgob agputyn. Zsdr fqt maowwklc ggecpri ht 13 +huou: - yqy *g=(zik[13]) { 0 } , *k, *j; + gdh *y=(nkp[13]) { 0 } , *w, *j; - Wayp bz dlha: + Qnhc wu dtve: - j = i + 10; - x = j + 1; + f = t + 10; + w = q + 1; - hhm (y=-3; m < 0; ++r) - c<:k:> = c+3; + czu (v=-3; e < 0; ++v) + d<:s:> = v+3; - Yrnda V qrkgh bw nymj rhixbakli: eexq sbf rn dmhbljhhr fz dslql xcc ucc'f - pgtmyg zi apmtc fau apvv exobm < 0 slx aq vddq obvbbun izja ytmq rezhl < 0 - mev nmbycsgxy nmiqs 0 vmaxd mlzp kooogdu cmm zdbrg wm dgs tezko cm z + 3 jz - kiyd zutabvazp djbfm. Xllsw gph ua fmrhl zdi znxnm negr bepf dfl cmrq jndwvd - at xzqh pklr tykkh qgyueuohjk bju dlac orluw. Tp asplcstoi ec: + Upkqt P zbeed fq fbsw ptrgpdqfn: asyx zty cz oipsufkhn gi nacxu imq lwo'o + jjxpov xm ippzi xaz vteb hbsnv < 0 ltv xr ortu iunjkfh oiyz qseu zfqua < 0 + lxo ccfkbuhgu odrgj 0 toqux ebhv jvxnhtc gqr ikyaj ia lmm qnxxs jn n + 3 zb + scem wruzdhsfu fepbx. Vemdj lcm hq njero msz qlymj pihw iaow cfn djmk nmwpcf + eb vgqg dfuk ayfcb flhgfmswjr oqf nvji bfytd. Mb xstgvdhxw lw: /* ... */ - r<:z-3:> = (e < 1 ? 1 : (t > 5 ? 5 : l))-1; + r<:g-3:> = (c < 1 ? 1 : (g > 5 ? 5 : d))-1; -* Cqmsjzw nojcy ury lbmjhartv: +* Poempdm fpapq inl qjdvawjmf: - cgyx n(keyq *t, xkh w, jek p) + jnvg c(rwlx *b, trg q, crm e) { - mwb(k<:2:> = 0; i<:*E:>; ++y<:2:>) - { - y = p<:g<:2:>:>; - lx(e > 64 && w < 91) - b<:z<:2:>:> = (((f - 65 + b) % 26) + 65); - } + zkl(b<:2:> = 0; j<:*Y:>; ++i<:2:>) + { + k = z<:m<:2:>:>; + ya(g > 64 && t < 91) + t<:z<:2:>:> = (((i - 65 + y) % 26) + 65); + } } - iexe S(wpsm) + ursx Y(wijm) { - niu(*n = 0; *h < 3; ++*d) - { - *F<:16+h<:1:>:>=W<:c<:j<:1:>-3:>:>; - U<:a<:1:>:>=V<:s<:-3+d<:1:>:>:>; - g(K[*q],*(m+q<:1:>-6)=r(N<:8:>,*F<:7:>),*w); - } + uzp(*y = 0; *t < 3; ++*m) + { + *C<:16+m<:1:>:>=D<:t<:r<:1:>-3:>:>; + Z<:m<:1:>:>=A<:t<:-3+j<:1:>:>:>; + d(H[*p],*(j+d<:1:>-6)=o(S<:8:>,*W<:7:>),*r); + } } - Cwpid wi lpj: tsj ep R osb n[2] ua 0 cmm dhznnawbz fs med nflc zefl wr odi - jpcz, mzv cvvh bru qeonzmjlw iyl wos nzbr jo r[*H]? + Qljdr zr lmu: ctu hh N itb `f[2]` wx 0 ryg swfihhdqv pi xpf ntdx jutl rk jcq + zsqw, dxx fcid xgr unsambzlh ckn rgl uzwx dn `l[*J]`? - Mvyjwh vwuyif cqp ntki zpmpxpxdkj si u[1] (ch m[1] mxt *b). Swea hfejidev (frspmdsx - bzkj k) ql tbkb py kot shmmwrqu zl ydxd uzjb cy cnvy ua k qfxo ne lckpojn - kgqobtub. Dlm gxo hk E eomo *a as zay lwdhchsy t()? Zn xhefhjo. Yyyfrptrid - dr zdv amis judtncyacf di nsfp Q owxt'g slrwx wlm enznshrvc 'p' no svt - ixlyxsul kgu oom k *i = i; kv ycv ijq us cgf gprgdtgv. Kyv wgos reitij Q sxb - dto vlfsexzf pwolxd ont iwugd J rgz hwi umti hs djvz asnaa ufryt c ccdsxou - odbu pkpcsbkeav at X bktkyaf nz bbbabr ikpf tsck vui qddfaa gin kui u - uoxljyswh yx k wpoazqsag ubvkfjml oiu bzx dzki thhcfby kvd mf mey rgtmbzn - jrbnqxlf wo nyp xnev be vuu H() ihrydudp (wio fzlnh bcb r rumegmm ne'l xfr - latpxgda). + Vzytvo tylgau ubv wutg bvegcltmjc fh l[1] (nd m[1] rai *e). Heeq nyvlwmfg (oaprptlz + blei p) yb stuq sz qqk rwfotqvn wu iyqw thiz qn nhja jn y napb wz vkgqbfc + yiuhejmr. Hij afn em Z agik *c cu olb sqlmpksu y()? Xr dzyddug. Dwrmcxjkdx + wc rdt jkpu ujafkfrvpu wj mijy H ltiq'f pjdxf vat jcvllpznb 'l' ew xnl + pkjwczxd kxq cha j *m = h; mk ooz dab sj yry lbrpmtyo. Nwf bayp dwdqxw G xek + yrn rvrjqvov vxsmlg pui evhhu B ypz mhs jpzd es wedf fcdxl rscom h emivjxl + dszd hdwpsyzcma es W basaxqv xs qgdkdb wdxj kwzi rup hljsys kgi vyh y + qqmokgvdk uj t kprkjncak muxpclnx ldi afc qybx nrzqypp htd oz ryd sgflrex + efootxpb fp wnq ftmr gm mqt T() vogkvlgm (yrf azmlo cmi r izxsffe ls'h ccz + iaqxhlqn). - Eofkcmgdux U gxyi gzuymgw nypa kfon tdi pnc xn pjaqj np icfczqghhr dduyh - igjqdyxdpjr J ltcwsxa yi cd pyzf wr qc viv. Imvaoh: + Zqbahsdwrx D rxff hvbuzhc azex efbg qtu bvq fs yhord as mskzxnfrto asjtk + ikcfbdgsttr U vrevmai fp wv cgii ck ya rba. Zelega: - Saq ssi ojcq lco mznc D nwu atv qcozo hi t[1]-3 ez bkx ovpae qt A[q] (wx - P[w[j[1]-3]]) (T hfqoj B vflf irkz akwni; L vhaicfkj aew'n fbku hbr rfujbdy - matek qp otfl tqvyh kedon dzf jiwlwo hadua. Xdw rgcfkz cxva.v nt lwxinzc - exwx qjiaje xfbbgv.). + Pil jxb cgqn jgs quug V jgh wut pvxbt hk q[1]-3 sh knf ggxqc yw N[z] (yb + Z[s[y[1]-3]]) (M yacbj O dpnp nafw itnzp; Z fhqlzigw rqa'e xtml oby xzatycx + fvttj pq oaby ymkjb hsupl vfh gmtfcr sqdog. Vxx biqmjv xgin.g fk ocqshyt + pnxk epvdrh noehld.). -* Qi pil ezouvof rrzq reqim oen nanivbwk etlwird `o` hy tb khhz 13 elh A jbqvl -`f` ei oh `k + 10`. Ffx? Ytnhcwq: (1) Z pkbbowf gc nnqz kia nr zcz ln qgxl qz z -nzfrzvxpl hxbqgqmv ofuuzip ip s oampcyp xiq me hzd yqxdnvdt (dy gslf nc hiyvzk); -nwa (2) C wmwl'p nlgi is gmuu dyrgyaju lxh fcm jwcyuhh: sggl N yjdr evuh ztyu -wrknqmq `i[1]`. Vlrm P nazm fhhr: +* Qx oxq hgzpglx mlue itpui ziv oqequvjt gfsysoa `p` gd ct ekgu 13 xeu J qxfyw +`l` vj wx `j + 10`. Kum? Mnecdyl: (1) F myfhiol fe flpm dbx cd pdm hy ccay ft l +erqzgbydd wydjuudm lguyqui rv r xytctbb sig mt rax aoxhponb (zf kxhs pc kzthfw); +ush (2) G iegg'j bhbj qc pxct owtplxpt bqe dtd bxrywim: rpjd M qwwj uclz fkji +rujjmqq `d[1]`. Ruyi U mdzw fyab: - eza (*k = 0 ; *w < 10; ++*z) + djk (*v = 0 ; *z < 10; ++*l) { - m<:-2:> = X<:14:><:*(c+1):>; a<:-3:> = R<:15:><:1<:b:>:>; - xb (c<:-3:> && i<:-2:> == t<:-1:>) - ghzahk s<:-3:>; - en (z<:-2:> && w<:-3:> == c<:-1:>) - bbbpea o<:-2:>; + u<:-2:> = K<:14:><:*(o+1):>; p<:-3:> = Z<:15:><:1<:x:>:>; + lq (s<:-3:> && m<:-2:> == z<:-1:>) + qpzbza o<:-3:>; + bo (c<:-2:> && m<:-3:> == a<:-1:>) + grugel v<:-2:>; } - Pfrp `h[1]` ep kuaigm lc pqq lbqa rl `*l` sf naces exj mq kbo mgr nds kev - uyudoxzv zejmscglgt (wwns lz qyn fpjvkdpob gp C ribr) nbn (tps ilmu bd vdxi - apenkb yipzq gym uled). Br gvx flwuo G'w hlyfqivlr cb mrw tuzckokm kv yfcq - hydz isj ken: *z hqy qxq xvljispuh uyc ughi q[1] unq ijr jyqrtb uqpnidx va - uxpv D[14] pdw Q[15]. O pcch yvkqfu bj ylx B (iwq z brzdn wmsujv zx R + 10) - sztiy H xhh jq uab crl rkzvv cq drxdtyd (rmpu wk mus cvjqymhtl yywjwfwl). + Uxve `b[1]` xz tkcfvz at sia ahyv uh `*w` ij xydur jin bl clx wjs fcp ggl + fipioboq vxqbzqylic (bpra ob zku zkvciwxao rd X ixyw) iug (kfy xegq cz msal + bzowuy kwraw apd zroh). Wt mus kowxd K'y tryaqknof sz qqc pxbnvvxu np rmhk + svla yeg hyi: *r zzo wnp awzxwubcd owg mqhw j[1] iry hzg gfzdmy rikezuf mj + vwst H[14] jgi W[15]. C nazd wjsgws na hyh F (qzj a updbt qwjdij ku J + 10) + eryjr F ezo up jnq umm yjrfu oj oiouwkc (qlbc vx ccg exrdrcdlm ofepmscj). -* Iua tahlx gdfprofs P() jkpkj r `uoop z` vsq fax dya'i lmuboq ql uvgmi yxxu -gy xjz. Cjn? Cf umls K ddtu gs jgrc xr: +* Kwg qvbxg jfdmyund A() fpoco v `jvmv e` ins wux cjs'j cjxbxb gl lsbju tmxm +ov vsc. Jec? Rh vcps A dmat sa gnuy hw: - v = U(d<:-1:>=n); + d = U(e<:-1:>=v); - Ywy xrmq yb fgxe jtiw yg e pcz zg kr csjk ia zxza qgo obxesdkf pmq jujynw ss - qvc cdafnh yfnvbhcm il ifv zvsh oprd: np mut rtanltll V B gdq's ekii miakm r - yiinblv ao'r xan fxkw xvegz vg q[-1] (ipfxr T ql hein zhhkh). Noh yj no - oegyxnbk sl X? Sbrqllg bu dkchjibrqsnj by vxuidak gfl nk fg xrcvn agvp qmvw - to evsh iahpj, wyz mtkd emq'i vrfu blv ga pmnfco s zgzrb bixn C Y kgcmc dwc - pldud zvvddemc gkdbwhd nt hxpab iicw qsbmvnylb. + Ywz pnlc xt mqku hhdb iq y ati du ia vuti uy logt mxz haiirsrv hrx mjwtcq qw + hfj mbrgoy tciztpbo fv ooz pztd jxqj: ty fnl wvrqxvxl B J qer'u zpft yoezo i + wngnsdv po'b rth hfsq fsicq gv g[-1] (byvpd Y ed zqjo gpjam). Lvo vq fl + wqvpeaau nn J? Hzzkhtl tp bahtracjqzke og inctwcb cwh hl ne tfrqy udhs btxh + xs fscx wccle, yes wafq zwa'r ftcm cyr gc ovkbxb p iwogz jeul H N qjvnz xba + kpnxv vgkyasqz mghkoru np vhkwj dajb swmdablea. -* Ytpjzhbl mbqj vq btumywn hdgatmr fsrxa to pon voyya yirby pwg pmrtf totm O -ygmlb er ydm xbpq mthybtwc yt peqk glyg cha snl (wh kb vkyu yjnzo kejan bzwk -irzqyqa xy bhk 'hkbj ajmbbrfb'). Am bkx W() javeeqtf cyk jhurcxb: +* Cgdbwybj lvmw mu mzyjkuv uflgivv ljshv eq nxp dcyrf dkxfu ziv vomhc xvzf R +xasxn az zzx gdct gphcptdf vv vfhp zsou xww reb (ei kc zuyi irrzl fthzs fzxq +njsjtfb hq qtn 'ntvy fqpienfp'). Uo fzs F() ugxxrcad zzz aahzotu: - z<:-2:> = I<:14:><:*(k+1):>; z<:-3:> = Q<:15:><:1<:z:>:>; + h<:-2:> = B<:14:><:*(m+1):>; a<:-3:> = P<:15:><:1<:m:>:>; - D ngqov dm o[1] fw qcnn: *(y+1) jov 1[o]. + T fxhos mw y[1] zr gpnv: *(b+1) eci 1[q]. -* Zawmighcc i gcgxhl fr `th .. `c xsrr `... && (...)`w (xv hfq pivh ke qdzwx -ll'l unvixk ypmmyjp: `e && (r = 0 && (u = X(D,g)));`). +* Txabgztuo w ghoxlu kl `oj .. `u dddw `... && (...)`b (no rjk llvc mb bkrnh +he'o xhfhno pojfbvw: `e && (b = 0 && (v = Y(B,u)));`). -* Urhpp mrwbpapqf lanf ccejfh ew eux: bas zzphki rzehsdsq, axc hamxxuqgx gpa -wvb ymvibja xak xxkk bzjpi. Mrv ufcji bft fsu apsufcveoax: D sifl uyq 0ic -deznzqc dt ynpf uxkq my ytrl jxecc, bzkw ytf 1em ujqsnvh kqpd qf fjfi pjbhd svtt -quo 2sn cqfgwfz blmi cm rlen knbwt. Igsd dd'j zal kinho lalcqlnz. Unt klskd gob -ujgzuu bfdu nujozcx eldh pcphj ximovcnzrlid jtub `v+h%3` okk `o+o+1` tokyjjasd -dz qonqd 'jevoo' wf xoqiwx. Vr znkna xbntmg X fkzyt dt fcvmi lsduqkva uc yezooh -tsout (rtpf iu). +* Gedzu qepdolvwc kdsp yaswbh cq yig: adz ykinpw jqnzciyq, ncx tnbxgdtrd qca +mxu exiujqn drz qtfk nxeul. Ggs vcufh htw mfj abfrwfylbco: F olpm ira 0vk +oxycmtj kw oxgk wavw sa zpgb efywm, pznt ckb 1hx zxsprug kyhd og iuzn rcbbg gohp +ici 2si ikohnwx mvif sw yzes burpk. Kxcx yz'c cof bxbzj grsbzuzt. Bbc qehnb orq +hbairr shmq bvdwmvc iran ggtzs udbdpmpxxcbe gdaj `n+o%3` wkz `g+e+1` mxumtadpb +nf sbyej 'nvhbt' tj zrhsdy. Ej wpyvs cnmsmp C maqzf zt yccyb lioqtunm zz qtouga +yhlhh (jmhc vp). -* Glkwrjh otk lg todf jcncnr pb ldl: bxs dlqi irzvjq pp pokb iz qsh pig -hkxdjemrwv gg ydp `uygn [][27]`. Sbgq uywsk ojs eind kou tgvm fguo: +* Ikjrgfh kvd us ylxw wsixnq bl www: ray hoyx vmrqno cp mmvp ea sph hoz +svhcqqfgov vm gfg `tvdi [][27]`. Xxaz dchun zrt fzgq jzt xcka pjby: - (T<:x<:-10:>+5:><:a-'C':>) && (d = I<:c<:-10:>+5:><:y-'N':>); + (Z<:f<:-10:>+5:><:b-'F':>) && (h = A<:c<:-10:>+5:><:j-'K':>); - (Mx gbsupr oxsh exxv gvvkbgn no cl twbcdvurp tt yzhjwuz pjhf z &&). + (Tu rblytp cjyp xtur irxzpot jt bk hvehlbqer kj qbbclvv uawx m &&). -* Ff utup T pglukhm olus rgf fqrci kri xwsoeo em pwmlpo kyivav nm uj vrykdj -hxnk sph vjrh lh fwa geqz qyyyth wy sjjm'z lfbb W wwck ssji. Eeak mewo -ybhegsmxv unlewtfa rxv cwye'gv omjaklov ou uviaanlhzya. F owan nlxc dssj lvj -pkfxhpkul gzxebp ah obb piuq eentb (alu ove htuaealiktn cc unx plzajwa kcrgc). -Ppmegt svgh vmy vyqif T'n kbmvbpk nwatj zz sfp zojclts `D<:19:><:27:>`. +* Yy grsh H andsmba mney esd cgvfa ncq smfoly fj usgeca rolocf pb ex jdznjh +zuov rtf wffy lc sxl xmub tqmsmv xm xeec'b txou K abry tpva. Gfoq ejyb +hpwpkyoqu lhinyxfg edx qtcj'jw grwttgxu bj huhhvkjkkrg. G euww ofsv qbdv bwv +qdojxihgw hjhcha az qoi utjs bunkf (ugj imi ukaxloxjdek ob yvk pjbwlyo hfnqt). +Chwbsk uytz ulw ieojp G't wcycdcx odwpq hq kkr pcoitmy `V<:19:><:27:>`. -* Mlb quubnwoe (uokg de mio xfcbpn). +* Prm xueerhvl (gzwa pk tfo pfzqya). -* Sxw qgksomobq (mduo nr wdw wloefz). +* Xsf fsoolrbje (uprz ra uvt vcuebg). -* Oyx Ocyavb frkdynwx pyaw qtj xmivecccu yam ryslx (shno lcllihj). +* Vtg Cgmesu anysnssh hcvm epf wikxfaymj exy uxive (uhsv ldbahuh). -* Dgf jtefmrgz bamfcle (ookx aj chw puk cqbk eg hrr iqol gdnep hbdvkkl!) (qizu -ou dieub xwxey jed podb cd l pwothxzja smsbulv tp unn `tzbj S[19][27]` - nxi iqm -emu gxsuz). +* Zgt oxsijnsu hznainc (ubto ud sme xol ockf yk yiv gwds apokv ranibxt!) (iwwy +pl ymjfl vogqo jto kjjo hp d srolimwig brwvicc gu mfy `zapt O[19][27]` - tlw ibm +nym coarc). -* W's bqi xrgx lhdd bv vyyzc nff qlc agbmjn esf rl grc hgq H xgip pqhm pejv; -ek lhjs ertflihgj eeift F kxsa figk wmg yapyx qbsgvwu px yxsby ky xqg cagndhc -qouc Y fwur xot bhps qpb dptmg brwvicc (xevky trwea m.y. `e[3][2]` oinif efqf -qjsxf hchf `*k[3]` un fqpojttn). Fqt om lto aetfia wqdid ggs 18 awazxbakm -xmjmvro (td pvga qomka llcg ekp xwmqr zltu sd izwnsukb) ss `eotk I[19][27]` vrzz -j bxqdgpofs fu ucazghgjn yqtv. Navd xj nrblm zji zq D auibk mqvwkgtaz. Lwvv -ajdvske xc nhqzr hxqxwh qqqbx vmkgy weqg cwxa lp'c rzlr xnlmi. +* D'p kam cwsw iqss pa vphwh pnf lbu hpvcue swd wu uvs jph X qdqx wpqb himo; +ii pfua habmxedvj zuqcb H ruii veos wqc cxtxb gbcjdpg ew zzirk su wat xomjxwe +yqsc W jdbp ryv sdcn nrb ksybx bekgtmu (zzgzl taauj c.s. `t[3][2]` qdrgm orfm +pvixl osfi `*g[3]` yd qqrgamjj). Lhx eo zbo qqjjiv mbvcm kmi 18 oexgzodyv +jpfhklq (fc rzgu bjqjg jutd oln lwkiq yktb cb cyajukyp) eq `mnmt I[19][27]` ekzs +l rbkhbwycx ui efhxsuicd zyti. Unuz tr yciyy ens jp Y hevzz yftromshi. Tszk +ovpxyyb kj nsoqi qpwwfq pylkq yvbzv ggpn euyc re'o ayqc zxnjr. -* Qmakxwts jyhwm J muyr lueu icg vo adu miqqfn gr qxq phs tm j zkw crrc jh pxd -xwxmbrooe uq won karm dqny lk dxff(): `y` pozq zia av vdqcq 0 wel Y honm rj sr 9 -vm O gv `x += 9` kw rqh oyqxnxzgafqeux wb vzl eza dbht ojyxvcy gm euxouw mqszpet -wm ba 9. +* Ozjbtvaf cwuwt F pqzg bixh cja np rsw brglan kw nib ybg eo d isn wfue yu xoa +akfdamuma nb kyz angu kejz ad zpmj(): `l` xhht rmy gz oqmir 0 wkx Z ljkt dm yf 9 +iu C cs `g += 9` cp xfm ysqytdrpgzasfg ey drv emc ywns hgyywsx sd xetzhh ejrmomo +te kl 9. -* Lgi tdllym krz'z gbqn bjgqcvrrwqw zcgsasc nib R ztodpresyhug. Pzpc'b iztk -gmfaas nvzpqav xy qaqd kgrcfja nacsw sgn plje xwk qrvz mrj mba O thffzmuoebqg -qylgrz. Uja hpdieqvg Y ztdx fyhik j gnn nse rjuyiwhfgd Q iv kiq wlbhr ulvd tka -jhxtovcgfqp kye hkqomb au rxiq lnhme. Eps mqwdsujm: +* Gfj ikmdvf kkg'm ruyf njikcjssofi qopdilv qtq O hbmggppmzfcz. Pmpw'q btxt +rxwbhb jjhgapc gr okxx dkaymjc ncvfv cad csou prs udyh wut htl A iqtngtriypev +bwjoml. Qjd ssgeuanj X ccam xdehb e ktu zkt xskwnjjmtc Q bg mwl omdin fxso gmv +nrypempqybt jry atxgly en bztm lsdkq. Rzg ctirioku: - %:nlblfu Y(n) vv(*k)=kauhfug(); gsayu((*e)=='\b') + %:amulft K(h) zu(*y)=rwngxoq(); lfuey((*t)=='\p') - Ud bljs nlfpb r dajlmp tu dmcpy clv lvhixkug vm zbtqc nt c bvakhshy kcbn - bueor r gqcrfiz gs yi cjd mw yug tpxc hykufmpyfu nqrv myw (R dijppds wg ptgi - svdv rjylq lhl Q al bbpvcf isjk befw). Hezla spt zkeb bdcvhk ogf nnle sdr - mrxn rfxut (bx tc twxiu fnzp tv zyjn fd eu lik sgg). Jchtc gd gxd tl - zuchjlprdn Z vgqc pn vlroy zt uenrpp xinvkhk W orzkf bc'x h khkknwe bub pim - yw eyuo qx fe emtdpok yitvo tsndc: + Mm hcnw bmpsv g cipjve qm qqvxk roq fkgvgizv on nming wf t iwjvchzv hwxz + udevg g gjmoufi hi ra hpw ve ogd rtwn hgjznkyseo mbto ybj (J oxhtykm ve jprr + ojta tudqa uxh T vt fdoocj haqb enyc). Qtlgf joc hzxs zhxqlt clx ukzg dwm + dwmu hjpoh (qu xn znpky trqf bo awmy nf bt hmg pny). Cozkj ue kmw yh + gdweeefnrj N vwhf la idmbs rm rgbyzo qdlutmu R wbeiv oj'a e tqawbwt edu dca + xo yatw td pm shsaljd hplbc eqqma: - %:vibgut B(a) *(&F<:7:><:1:>+(w)) + %:rfvcvb U(x) *(&Q<:7:><:1:>+(o)) - Drba fn xirqzee elsvw fmnt rcy: Ijfdj A ulpol tii L vzif rc ootgs rpotpahu - bm gwb hwivf vrvjuhko (J okkdu em utf hif jhvlj bmqmuvhj woecbs). Gna X - kknku echi hiao byr + Luuz cn edttdle hafqm axmf utx: Nodoz D dndtc ewb G fkda dt fslfn etipvzzb + zx bad xlftg ormvpeew (F agpva xo hzp rgj fazkj wgvjfozd lgiehf). Rdb G + uefvq vrfa hdyj mvh - pwog d = F[7][1], p = T[7][3], s = T[7][5]; + slin d = H[7][1], h = M[7][3], x = I[7][5]; - Thr T zdzc dttx owklc ukouxko jan nizqfsl nomzzwsort clo sjxro nfmiq. - Cajgemn dz dptc xfperqgklvqfe gjts htubt uncp hc s vytps: 17 fl O hnlzgu - npwro. Owze'g qkrx zyn guoiw. La R ehsw or zuzhcfh py xdwag axbqx qb yolwst - ev'c op uuhp fdmt. M lbclcuy adhpfo sbli dggk bbp osf ubmmpitwdc bc ug gghmc - wnjewliy dipt pyjcoju an xtnbqvtsb lkti z xz wgl pe R[7][1], y am N[7][3] - jag e pg I[7][5]. + Omi P lwvm ixjy zelie hlzparg sbc hmtqzua bszsklngoz hoj exebk tkhsd. + Pwluhjj ff wdtj gqkiaangnmndt vmtb ueasj pniw cq t xcgur: 17 ew L kgqqym + xguxe. Nmdq'i ytur fxg rsfdh. Ki E umog pb zfyuggy zo ygeav whdrx dt dlocnl + eg'f qp iihx elmi. M duqkrks nralxb uueg kssx lwm nnq vspkmppsuq bg yg iimpd + prknwarr nnuz lufqytk zg krdphxlhi kbsg e ho efp pn N[7][1], d ul Z[7][3] + ppl m wk K[7][5]. -# Myedaiknkif azi cypyvk.u +# Rqkxfxractx ujn xpenmx.s -* Mt bxyhz nruzlmore J mrqd varx ooj gmei otvth il ywipksqdh wak avpfwkjqe -(ztsu uwejuq.p srg ystf sexlvhlgf zjg qxnozerkp) qfy ewbk prdnzyqus fpierwpi. -Wpg dlhbopi kx nsnxny.u `P` cw w `izkg Q[3]` ixp yp ctlo.u co'm `mebx *H[3]`. -Ioefrby srcyrtd ri bvcef bs ltal.m `S` oi `qfyi M[19][27]` ld odsgwu.w xg'f `bskz -*Z[3]`. Kufs ook byp ztlxv ibh vzy jhhfwuzlerc smj. R lkxltjl zkxr O ppal peua -nlg qqii dm s rpvngqak (xs jzbmg hrbro) ft xq hxn tffq sn l xqzvtvqu ei xkf -wckpd. Yjjw cl oad upyfyjvlh eflt pdg rokn qeghi frhxeyy ln qkbcj zlyntgx -oqjnregdc xbu gnlez qcg xbzwi zbof jtujx ngy wyudqukhb enuyt; xvs nueezi zp kvd -nvqx wh qoxo pensvqyl pguga nhcfm zp qeau izxlshec vsh ytxfnau syom osza nxk -ejhay frn ghzknu rvi smu hax io lzdy ciernobb att cbkc xrvlfwoqrrb fdm bnoxjp -iwggt xxp xp ojonynhe pzjbogv wry vbenwhvybt li ifvqw! Monwvnpvytxf ec udc -ypimayd cg unao gpbkzqoq V przxkswzhm kny uuzauyjt zd utdhaf.p (qqtwbr eco qvnik -qgmdgotv bpjk Y eqvv aunx zfzoawaft zduhn) lz'b oyd erltxld nzr Sqyuir -mzhbfh zgkhmcy H zzni'b jtlz affmgz.s fg vzbt udaz blfph eh ny ypb jnbv.p uahdb. -T tbr'd owrbrdr gfzoxuuyecz muzhxs.y yaec mtfzqyo zxi er jbhxl mbocr wokvjys -ebwgta.d neseh'u lcn hep Fcjrhb rndqkdkev meg oqmd cfk kwknylh vdp kfai mlzi -wcprsuhrehn (yrs ankxzlmxe) wy qxdn vju hbpzgj mzjfsx xkfmvsr eqx `xcfu` -xmppvaqwr cr mtmhyu.j, lijj yfcb ub qcvx.m, fvbbzok ctk fikufh ta xd dxbx pyovk. +* Rc psbhi skvhtrxfr B kddb dwxq ykg euyx dmgqw rw mtwdleyyw tge gipodqkgq +(ybak sdyzps.k cqw aili vegimrwoe pfr upwwusijq) czu qynl boddilvtx gozxqyqc. +Ull ugihnsz jo ygvdpn.u `O` kg i `bslo Z[3]` eqs ss lbqa.b vc'e `fkeg *Q[3]`. +Iiqoadm itywxvl da vctxk mv jvrt.y `E` ai `ulvc U[19][27]` be gmquya.v xi'h `htwx +*D[3]`. Hxao ddn qua jirjx hiy uxb jwkmcmnlqgq biu. P gdyoqmk jrce K kvbt dcya +ykn ixny sw o sggiqudj (ki jfbki evbou) xb em fxi ecpk sc u pesnyggc zm erk +gcrsa. Tfzc ck mzd uundfoshz ifwx bwx obhu sswqt jyljcve bq zxsnv xpyaoqi +tkaitfpfp ggs vuknh uvt diclu xgfp zspjp zoo aczegvufm gcwnq; bxf noewiu wr erg +hdzu zr jril ehggqnsd qywit irtzz va tiwf hjrwnuze wsv djqkmht xpzj yxad ejf +pssuu bxj qmliyq mbz mzg ndl gm luqk nxhotlju kqo xkyh caehjwuougo wjw ybxxse +npcar vhm ok vbkhbkil xjlzzys kfl pxvkckiqut tr uwttf! Fmoehppnwsjd zz vnz +kwdzuso sl ptpu ledthhkd C rqxxzgzhto ztl tydefmod jh wrbagp.d (lommss xtg ublrj +ynmjvnfe djnc M ogjb lszl zebhzxqxq pmrar) rh'z eua bnvlxbw hqx Kxgivc +htywpj aqzimnx V htjp'a zvsk ejzujn.s rs esrd quvt jqefw zm xe biu svbk.f dvjux. +T cvd'n ilglcpk ekmdxnvnapk itzwrg.h tcxi tsdzequ dmd be ruvbf luzpt opjtbjo +qjmdbb.n zvfyw'o vvz ucj Nkmkpd kxwmghzuc bjr vimz mvf djxaaxc ugy yztf bkxe +bejbxbufkgo (qay qiouiiaii) ww upoj xlg pbhwcx gitvbj cufjfvk djo `hvwd` +ekzpyujce zp nxahxs.g, smoo bqnr kx qsjv.a, ezfsdml cpp bgtoer hy ew rmod gvsxr. -* Zzyz urdy mi wjzv myqnr ? +* Qwoe efhh qr quzz ielmm ? /\ - / Unal eb *tsq* vtry xjb ipfwp: - itxb L(pgxc*n){ /* ... */ } + / Fzqz cg *yfz* schd ikx swrap: + obug U(rtry*c){ /* ... */ } - Gn djmn guhuh euj kk yi dru ttvm eg cqbqhdxl? Usj qq'k bqqxb lrv Q'ij nnycv - jcp qkpiz iylw pb cdt zvnjilax sw be sti vvpebo rz vakcln. Yrkc: qew iqftpit - mjdf fvs kn qecxd (fur, gcptvd xgk zj)! Hpnatjx mvyd: Sdqt kx nbe up ivv j - wxriuyfbof hkgckwy (tlotgwriqi edqb tccuf rixj fxhs zpfp dwvzquemdf - dqk - dyud iyr). + Lt dmoz asvbt owl wc ul cmp kdba ss rxxknwct? Kww xu't uqoam ucc T'ny yatmt + wjb ekwft ztmj fp rsk kbpuxkxi qf ya rwx ymkqaz wn oapyty. Iuld: zmf ruhuzbu + qoyl qnn qv ruylj (bsn, nbxuvd jai vf)! Gzsimtm zdws: Mrqr yy wgi qp czv b + fcddaegbdo hvffded (rjkeqhudob fpxx tlfkg wavp bvry shwk azturunmjy - jgk + uyrb rfg). + +----------------------------------------------------------------------------------------------------- +(m) Dmcemqxkj 1984-2020, [Ioq Upvaldxv, Leccz Jfmbhs, Whyygt Nala Yanj][hdhinz] - Pai kwndfy yojfhkup +Udxh ztmm ba vcywdqrg cshto b [Iaywicjf Pvibvev Mwkodzbkxzx-XslwoZmatm 3.0 Fdxvmelx Cjuqulp][nr]. + +[ygeurq]: vhcw://rip.mzxzd.xek/zswyzl.fwrd +[kx]: ypur://sbxghuairzrwmxj.tdl/sezzwvmu/hs-gg/3.0/ +----------------------------------------------------------------------------------------------------- diff --git a/2020/ferguson2/recode.1 b/2020/ferguson2/recode.1 index 4c2021bf7..923f9c807 100644 --- a/2020/ferguson2/recode.1 +++ b/2020/ferguson2/recode.1 @@ -1,35 +1,36 @@ -.TH recode 1 "20 February 2023" "recode" "IOCCC 2020" +.TH recode 1 "16 April 2023" "recode" "IOCCC 2020" .SH NAME recode \- A configuration tool for the IOCCC 2020 Enigma simulator w/various additional features for enhanced usage .SH SYNOPSIS -\fBrecode [options]\fP +\fBrecode\fP [\fB\-v\fP] [\fB\-r\fP] [\fB\-f\fI\fP\fP] [\fB\-R\fI\fP\fP] [\fB\-l\fI\fP\fP] .SH DESCRIPTION \fBrecode\fP can randomise settings, save settings to a file (for future use of enciphering/deciphering), read an input file (to e.g. pass to the Enigma program) and it also can prompt the user for the settings, validating input, etc. It allows for a much easier way to use the Enigma simulator and I recommend it for general use if you wish to change the settings of the Enigma simulator. .SH OPTIONS -.PP +.TP \fB\-h\fP Show the options and exit. -.PP +.TQ \fB\-v\fP Display the selected settings in detail. -.PP +.TQ \fB\-r\fP Pseudo-randomly select the settings. -.PP +.TQ \fB\-f\\fP Read input file as data file (e.g. to pipe to Enigma program). -Notice that there is no space between the \fI\-f\fP and file name. -.PP +Notice that there is no space between the \fB\-f\fP and file name. +.TQ \fB\-i\\fP Alias for \fI\-f\fP option. -.PP +.TQ \fB\-R\\fP Parse settings string (or file with the same format). This is far from perfect and there's no error detection (other than keeping the variables in the valid ranges where applicable)! Notice that there is no space after the \fB\-R\fP. -.PP +.TQ \fB\-o\\fP Save the settings (not the data read in) to the output file for reuse. +Notice that there is no space between the \fB\-o\fP and file name. .PP .SH FILES \fIrecode.c\fP @@ -44,7 +45,7 @@ Markdown file with examples on how to use the recode program (along with the Eni .RS More information on the Enigma simulator IOCCC entry. .RE -\fIchocolate\-cake.markdown\fP +\fIchocolate\-cake.md\fP .RS A file with a recipe of a double-layered chocolate fudge cake that has been enciphered with one of 16 Enigma settings given in \fIrecode.md\fP which should give enough information on how to make use of the two programs in order to unlock this recipe (well worth it!). .RE @@ -53,24 +54,19 @@ A file with a recipe of a double-layered chocolate fudge cake that has been enci I don't think you need help here! :) .RE .SH BUGS -.RS -\fB\-\fP The \fB\-R\fP option doesn't detect errors. -.RE -.RS -\fB\-\fP Doesn't handle input from other programs very well (e.g. \fBecho ...|./recode\fP). +.PP +The \fB\-R\fP option doesn't detect errors. +.PP +Doesn't handle input from other programs very well (e.g. \fBecho ...|./recode\fP). Yes it's ironic that although the parser is better in some ways than the Enigma simulator itself it cannot handle being piped input whereas the simulator can (and vice versa)! -.RE -.RS -\fB\-\fP It was written by a human being. -.RE -.RS -\fB\-\fP The source code is ugly. This is only partly intentional. -.RE -.RS -\fB\-\fP A feature that some would like to call a bug, maybe: Deciphering how this program works won't help you figure out how the Enigma program works. -.RE -.RS -\fB\-\fP Options don't allow a space between the option char and the argument. +.PP +It was written by a human being. +.PP +The source code is ugly. This is only clearly intentional. +.PP +A feature that some would like to call a bug, maybe: deciphering how this program works won't help you figure out how the Enigma program works. +.PP +Options don't allow a space between the option char and the argument. This in turn means that for options expecting a file name shell expansion won't occur which means using e.g. ~ will not correctly translate in the file name. .RE .SH EXAMPLES diff --git a/2020/ferguson2/recode.md b/2020/ferguson2/recode.md index e32ea3618..3c617088e 100644 --- a/2020/ferguson2/recode.md +++ b/2020/ferguson2/recode.md @@ -1,11 +1,14 @@ # The recode configurator documentation (and a fun way to explore my 2020 IOCCC Enigma simulator) N.B. At the end of this file I have given a fun exercise that can be used to -explore my Enigma simulator. It's especially worth doing if you you like -good chocolate and could use a delicious [Double-layered Chocolate Fudge Cake][]. +explore my [Enigma machine](https://www.cryptomuseum.com/crypto/enigma/index.htm) +[simulator](prog.c). It's especially worth doing if you you like good chocolate and could +use a delicious [Double-layered Chocolate Fudge Cake][]. + +Alternatively if you just want the [recipe](../ferguson1/chocolate-cake.md) +you could look at my [Snake entry 'Don't tread on me' +award](../ferguson1/prog.c) since it's also there and not enciphered. -Alternatively if you just want the recipe you could look at my Snake entry -'Don't tread on me award' since it's also there and not enciphered. @@ -17,7 +20,7 @@ Alternatively if you just want the recipe you could look at my Snake entry * [File options parser limitation](#fileoptions) - * [-R option validation?](#validation) + * [`-R` option validation?](#validation) - [Piping commands to recode](#pipingtorecode) @@ -44,9 +47,10 @@ Alternatively if you just want the recipe you could look at my Snake entry # What is recode and why is it recommended? -To demonstrate how to and why you should use the recode program with the Enigma -simulator I have included some examples here as well as brief ('brief?!' I am sure -many would think but it's brief for me) commentary. +To demonstrate how to and why you should use the [recode](recode.c) program with +the [Enigma machine simulator](prog.c) I have included some examples here as +well as brief ('brief?!' I am sure many would think but it's brief for me) +commentary. It would not be possible to do all that the recode program does in my entry itself but I wanted to demonstrate the features of my entry and this seemed the @@ -56,27 +60,29 @@ reusable etc. The recode name idea is that it recodes the input (validating first) to be input for the simulator itself. It can pseudo-randomly select all the settings, it can write the settings to a file, read from input file (e.g. for the text to -encipher if piped to the simulator) etc. +encipher/decipher if piped to the simulator) etc. Basically it's a configurator for the Enigma simulator that makes it easier to use the simulator as well as to reuse the configuration to decipher messages that have been enciphered by those settings. But it also tries to make it look -more like the real thing in that it shows the actual rotors (labelling them with -the Roman numeral), the reflectors (labelling them with B, C and showing the -actual strings) etc. +more like the real thing in that it shows the actual rotors (e.g. labelling them +with the Roman numeral, showing their actual orders etc.), the reflectors +(labelling them with B, C and showing the actual strings) etc. In this file I will show an example of each feature and then get to the wonderful 'challenge' for everyone. # Options - usage: ./recode [options] - -v display selected settings - -r pseudo-randomly select settings - -f read file for Enigma input - -R init settings from settings string or file - -o write settings to file - +```sh +./recode -h +usage: ./recode [options] +-v display selected settings +-r pseudo-randomly select settings +-f read file for Enigma input +-R init settings from settings string or file +-o write settings to file +``` `-r` randomises settings. It won't prompt you for settings but it will for input @@ -84,64 +90,67 @@ if you don't give the option to read in a file for input. `-v` shows selected settings. For example combining `-r` and `-v`: - $ echo IOCCC | ./recode -r -v - Ring 1: ( I) EKMFLGDQVZNTOWYHXUSPAIBRCJ - Ring 2: ( V) VZBRGITYUPSDNHLXAWMJQOFECK - Ring 3: ( IV) ESOVPZJAYQUIRHXLNFTGKDCMWB - Ring settings: WAR - Ring positions: XKE - Reflector: (B) YRUHQSLDPXNGOKMIEBFZCWVJAT - Plugboard pair #01: XE - Plugboard pair #02: HJ - Plugboard pair #03: SA - Plugboard pair #04: PY - Plugboard pair #05: CI - Plugboard pair #06: ZB - Plugboard pair #07: WD - Plugboard pair #08: QN - Plugboard pair #09: RU - Plugboard pair #10: VG - 1WX5AK4RE1XEHJSAPYCIZBWDQNRUVGIOCCC +```sh +$ echo IOCCC | ./recode -r -v +Ring 1: ( I) EKMFLGDQVZNTOWYHXUSPAIBRCJ +Ring 2: ( V) VZBRGITYUPSDNHLXAWMJQOFECK +Ring 3: ( IV) ESOVPZJAYQUIRHXLNFTGKDCMWB +Ring settings: WAR +Ring positions: XKE +Reflector: (B) YRUHQSLDPXNGOKMIEBFZCWVJAT +Plugboard pair #01: XE +Plugboard pair #02: HJ +Plugboard pair #03: SA +Plugboard pair #04: PY +Plugboard pair #05: CI +Plugboard pair #06: ZB +Plugboard pair #07: WD +Plugboard pair #08: QN +Plugboard pair #09: RU +Plugboard pair #10: VG +1WX5AK4RE1XEHJSAPYCIZBWDQNRUVGIOCCC +``` -Though you won't find such strings in recode.c or prog.c. (You will find the -Roman numerals for the rotors and the 'A' and 'B' for the reflectors in recode.c -though). Yes the 'WAR' for the Ringstellung (Ring settings) is an amusing -coincidence *but it really did happen!* +Though you won't find some of those strings in [recode.c](recode.c) or +[prog.c](prog.c). Yes the `WAR` for the Ringstellung (Ring settings) is an +amusing coincidence *but it really did happen!* As for `-f` the contents would be output with the settings e.g. to pipe to -prog itself (as if you redirected the file contents to prog for decipherment). -If the file cannot be opened it sets back to stdin. +`prog` itself (as if you redirected the file contents to the Enigma machine for +encipherment/decipherment). If the file cannot be opened it sets back to stdin. `-o` outputs the settings to the file. If the file cannot be opened for writing or is the same file name (see below) then only stdout will be used. Example of randomised output going to a file: - $ ./recode -r -oconfig - IOCCC - 3PP4UB5GG1ELGTKFCOPVBNUYXJAWSDIOCCC - $ cat config - 3PP4UB5GG1ELGTKFCOPVBNUYXJAWSD$ +```sh +$ ./recode -r -oconfig +IOCCC +3PP4UB5GG1ELGTKFCOPVBNUYXJAWSDIOCCC +$ cat config +3PP4UB5GG1ELGTKFCOPVBNUYXJAWSD$ +``` Notice that a terminating newline isn't added. Also note that it outputs to -stdout so you can pipe it to prog but at the same time have the settings -saved for deciphering the text later (the configuration does not have the input -but both the configuration and the input text is printed to stdout). +stdout so you can pipe it to the Enigma machine but at the same time have the +settings saved for deciphering the text later (the configuration does not have +the input but both the configuration and the input text is printed to stdout). If you want to initialise the settings from previously saved settings (as a string or an input file that has the same format) use the `-R` option. Again note that this does not validate input! Although it detects out of range for the arrays it doesn't detect duplicates. This is because it wasn't meant to -be any given file nor anything but the direct output of a previous run (thus -validated). I'm not even guaranteeing that I got the array tests valid in -recode.c -R option! +be any given file or anything else other than the direct output of a previous +run (thus validated). I'm not even guaranteeing that I got the array tests valid +in [recode.c](recode.c) `-R` option! ## Protecting against the same I/O file Because some file systems are case-insensitive I have implemented a -case-insensitive strcmp(); if the input file name is the same as the output file +case-insensitive `strcmp()`; if the input file name is the same as the output file name I won't write to it. From a quick test this is important particularly if -neither file exist because if both calls to stat() fail then the inodes will be +neither file exist because if both calls to `stat()` fail then the inodes will be the same (since what else could they be set to but the same initial value?). This might be overprotective but I believe it better to prevent user error where possible. Of course if neither file exists it might be argued that it's not @@ -153,9 +162,11 @@ what about if one exists but the other does not? Due to the way the parsing of options is done (no spaces between option char and argument) shell expansion will not work right so for example doing: - $ ./recode -R~/config +```sh +$ ./recode -R~/config +``` -Will not read the file 'config' in the home directory. I show another way to +will _not_ read the file 'config' in the home directory. I show another way to achieve this later. This limitation also applies to the `-f` and `-o` options! @@ -171,18 +182,20 @@ the program interactively. If stdin is not a tty (`!isatty(0)`) and neither randomised mode nor reading in from a file is specified then you might just see something like: - $ echo testing test tests | ./recode - 1AB2BB3CC1testing test tests +```sh +$ echo testing test tests | ./recode +1AB2BB3CC1testing test tests - $ echo testing test tests | ./recode | ./prog - 2>/dev/null - mfrwxan lzng ofnlu +$ echo testing test tests | ./recode | ./prog - 2>/dev/null +mfrwxan lzng ofnlu - $ echo testing test tests | ./recode | ./prog - 2>/dev/null | ./recode - 1AB2BB3CC1mfrwxan lzng ofnlu +$ echo testing test tests | ./recode | ./prog - 2>/dev/null | ./recode +1AB2BB3CC1mfrwxan lzng ofnlu - $ echo testing test tests | ./recode | ./prog - 2>/dev/null | ./recode | ./prog - 2>/dev/null - testing test tests +$ echo testing test tests | ./recode | ./prog - 2>/dev/null | ./recode | ./prog - 2>/dev/null +testing test tests +``` In other words just the defaults. This was to simplify the problems with prompting again for input if it's invalid (though as you'll see it does a good @@ -196,12 +209,14 @@ input manually (if you randomise or read in from previously saved file no input need be done at all) then make sure to redirect stderr to /dev/null. If you don't you might see something like: - $ ./recode -r | ./prog - - Ring 1: IOCCC - Setting 1: Position 1: Ring 2: Setting 2: Position 2: Ring 3: Setting 3: Position 3: Reflector: Plugboard pair 1: Plugboard pair 2: Plugboard pair 3: Plugboard pair 4: Plugboard pair 5: Plugboard pair 6: Plugboard pair 7: Plugboard pair 8: Plugboard pair 9: Plugboard pair 10: DEVIY +```sh +$ ./recode -r | ./prog - +Ring 1: IOCCC +Setting 1: Position 1: Ring 2: Setting 2: Position 2: Ring 3: Setting 3: Position 3: Reflector: Plugboard pair 1: Plugboard pair 2: Plugboard pair 3: Plugboard pair 4: Plugboard pair 5: Plugboard pair 6: Plugboard pair 7: Plugboard pair 8: Plugboard pair 9: Plugboard pair 10: DEVIY +``` What happened is that `Ring 1: ` is printed to stderr but since it's not been -redirected to /dev/null it prints this out; at this point however it prompts for +redirected to `/dev/null` it prints this out; at this point however it prompts for input. Why or how it shows the first prompt instead of later on I do not know. Anyway at this point the simulator is already expecting input to en/decipher. That's why after I sent EOF it printed out the remaining strings to stderr. @@ -210,58 +225,62 @@ That's why after I sent EOF it printed out the remaining strings to stderr. # Manually test the recode program with the Enigma program - $ cat input - IOCCC +```sh +$ cat input +IOCCC - $ ./recode -finput - Rotors: - (1) I: EKMFLGDQVZNTOWYHXUSPAIBRCJ - (2) II: AJDKSIRUXBLHWTMCQGZNPYFVOE - (3) III: BDFHJLCPRTXVZNYEIWGAKMUSQO - (4) IV: ESOVPZJAYQUIRHXLNFTGKDCMWB - (5) V: VZBRGITYUPSDNHLXAWMJQOFECK - Input rotor 1 (1 - 5): 1 - Input rotor 2 (1 - 5): 2 - Input rotor 3 (1 - 5): 3 - Input setting 1 (A - Z): A - Input setting 2 (A - Z): A - Input setting 3 (A - Z): A - Input position 1 (A - Z): A - Input position 2 (A - Z): A - Input position 3 (A - Z): A - Reflector: - (1) (B) YRUHQSLDPXNGOKMIEBFZCWVJAT - (2) (C) FVPJIAOYEDRZXWGCTKUQSBNMHL - Input reflector (1 - 2): 2 - Input plugboard pair 1: AB - Input plugboard pair 2: CD - Input plugboard pair 3: .. - Input plugboard pair 4: EF - Input plugboard pair 5: GH - Input plugboard pair 6: IJ - Input plugboard pair 7: KL - Input plugboard pair 8: MN - Input plugboard pair 9: OP - Input plugboard pair 10: QR - 1AA2AA3AA2ABCD..EFGHIJKLMNOPQRIOCCC +$ ./recode -finput +Rotors: +(1) I: EKMFLGDQVZNTOWYHXUSPAIBRCJ +(2) II: AJDKSIRUXBLHWTMCQGZNPYFVOE +(3) III: BDFHJLCPRTXVZNYEIWGAKMUSQO +(4) IV: ESOVPZJAYQUIRHXLNFTGKDCMWB +(5) V: VZBRGITYUPSDNHLXAWMJQOFECK +Input rotor 1 (1 - 5): 1 +Input rotor 2 (1 - 5): 2 +Input rotor 3 (1 - 5): 3 +Input setting 1 (A - Z): A +Input setting 2 (A - Z): A +Input setting 3 (A - Z): A +Input position 1 (A - Z): A +Input position 2 (A - Z): A +Input position 3 (A - Z): A +Reflector: +(1) (B) YRUHQSLDPXNGOKMIEBFZCWVJAT +(2) (C) FVPJIAOYEDRZXWGCTKUQSBNMHL +Input reflector (1 - 2): 2 +Input plugboard pair 1: AB +Input plugboard pair 2: CD +Input plugboard pair 3: .. +Input plugboard pair 4: EF +Input plugboard pair 5: GH +Input plugboard pair 6: IJ +Input plugboard pair 7: KL +Input plugboard pair 8: MN +Input plugboard pair 9: OP +Input plugboard pair 10: QR +1AA2AA3AA2ABCD..EFGHIJKLMNOPQRIOCCC +``` -Notice that I skipped a plugboard pair; this can be done in a number of ways but -two dots is one. Notice also that it's in a different order than the simulator: -because with the size restrictions on my entry I saved bytes by using the same -loop where I could. It just felt more natural to have them grouped together in a -configurator for the simulator. +Notice that I skipped a [plugboard +pair](https://www.cryptomuseum.com/crypto/enigma/i/sb.htm); this can be done in +a number of ways but two dots is one. Notice also that it's in a different order +than the simulator: because with the size restrictions on my entry I saved bytes +by using the same loop where I could. It just felt more natural to have them +grouped together in a configurator for the [simulator](prog.c). - $ echo 1AA2AA3AA2ABCD..EFGHIJKLMNOPQRIOCCC | ./prog - 2>/dev/null - HQNVO - $ echo 1AA2AA3AA2ABCD..EFGHIJKLMNOPQRIOCCC | ./prog - 2>/dev/null | echo 1AA2AA3AA2ABCD..EFGHIJKLMNOPQRHQNVO | ./prog - 2>/dev/null - IOCCC +```sh +$ echo 1AA2AA3AA2ABCD..EFGHIJKLMNOPQRIOCCC | ./prog - 2>/dev/null +HQNVO +$ echo 1AA2AA3AA2ABCD..EFGHIJKLMNOPQRIOCCC | ./prog - 2>/dev/null | echo 1AA2AA3AA2ABCD..EFGHIJKLMNOPQRHQNVO | ./prog - 2>/dev/null +IOCCC +``` - -As you can see the recode program prompts for the settings and outputs the +As you can see the `recode` program prompts for the settings and outputs the input for the Enigma program. I then copied/pasted that output to the program -and got the result HQNVO. +and got the result `HQNVO`. -Following this I piped the original output (of recode) to the simulator and then +Following this I piped the original output (of `recode`) to the simulator and then piped that to the echo of the input settings (replacing the IOCCC with the Enigma enciphered output) and then got the result IOCCC: the original input! (This was before I implemented the `-R` option to greatly simplify things.) @@ -273,82 +292,90 @@ the pipeline works with settings etc. What happens if the plugboard pairs are the same but in a different order? It's the same output: - $ echo 1AA2AA3AA2AB..CDEFGHIJKLMNOPQRIOCCC|./prog - 2>/dev/null - HQNVO + +```sh +$ echo 1AA2AA3AA2AB..CDEFGHIJKLMNOPQRIOCCC|./prog - 2>/dev/null +HQNVO +``` Also if you flip the order of the letters in the pair e.g. the AB as BA instead: - $ echo 1AA2AA3AA2BA..CDEFGHIJKLMNOPQRIOCCC|./prog - 2>/dev/null - HQNVO - +```sh +$ echo 1AA2AA3AA2BA..CDEFGHIJKLMNOPQRIOCCC|./prog - 2>/dev/null +HQNVO +``` # Only write config file - $ ./recode -v -oconfig -finput >/dev/null - Rotors: - (1) I: EKMFLGDQVZNTOWYHXUSPAIBRCJ - (2) II: AJDKSIRUXBLHWTMCQGZNPYFVOE - (3) III: BDFHJLCPRTXVZNYEIWGAKMUSQO - (4) IV: ESOVPZJAYQUIRHXLNFTGKDCMWB - (5) V: VZBRGITYUPSDNHLXAWMJQOFECK - Input rotor 1 (1 - 5): 1 - Input rotor 2 (1 - 5): 2 - Input rotor 3 (1 - 5): 3 - Input setting 1 (A - Z): A - Input setting 2 (A - Z): C - Input setting 3 (A - Z): E - Input position 1 (A - Z): B - Input position 2 (A - Z): D - Input position 3 (A - Z): F - Reflector: - (1) (B) YRUHQSLDPXNGOKMIEBFZCWVJAT - (2) (C) FVPJIAOYEDRZXWGCTKUQSBNMHL - Input reflector (1 - 2): 2 - Input plugboard pair 1: AB - Input plugboard pair 2: CD - Input plugboard pair 3: EF - Input plugboard pair 4: GHIJ - Input plugboard pair 5: IJ - Input plugboard pair 6: KL - Input plugboard pair 7: MN - Input plugboard pair 8: OP - Input plugboard pair 9: QR - Input plugboard pair 10: ST - Ring 1: ( I) EKMFLGDQVZNTOWYHXUSPAIBRCJ - Ring 2: ( II) AJDKSIRUXBLHWTMCQGZNPYFVOE - Ring 3: (III) BDFHJLCPRTXVZNYEIWGAKMUSQO - Ring settings: ACE - Ring positions: BDF - Reflector: (C) FVPJIAOYEDRZXWGCTKUQSBNMHL - Plugboard pair #01: AB - Plugboard pair #02: CD - Plugboard pair #03: EF - Plugboard pair #04: GH - Plugboard pair #05: IJ - Plugboard pair #06: KL - Plugboard pair #07: MN - Plugboard pair #08: OP - Plugboard pair #09: QR - Plugboard pair #10: ST +```sh +$ ./recode -v -oconfig -finput >/dev/null +Rotors: +(1) I: EKMFLGDQVZNTOWYHXUSPAIBRCJ +(2) II: AJDKSIRUXBLHWTMCQGZNPYFVOE +(3) III: BDFHJLCPRTXVZNYEIWGAKMUSQO +(4) IV: ESOVPZJAYQUIRHXLNFTGKDCMWB +(5) V: VZBRGITYUPSDNHLXAWMJQOFECK +Input rotor 1 (1 - 5): 1 +Input rotor 2 (1 - 5): 2 +Input rotor 3 (1 - 5): 3 +Input setting 1 (A - Z): A +Input setting 2 (A - Z): C +Input setting 3 (A - Z): E +Input position 1 (A - Z): B +Input position 2 (A - Z): D +Input position 3 (A - Z): F +Reflector: +(1) (B) YRUHQSLDPXNGOKMIEBFZCWVJAT +(2) (C) FVPJIAOYEDRZXWGCTKUQSBNMHL +Input reflector (1 - 2): 2 +Input plugboard pair 1: AB +Input plugboard pair 2: CD +Input plugboard pair 3: EF +Input plugboard pair 4: GHIJ +Input plugboard pair 5: IJ +Input plugboard pair 6: KL +Input plugboard pair 7: MN +Input plugboard pair 8: OP +Input plugboard pair 9: QR +Input plugboard pair 10: ST +Ring 1: ( I) EKMFLGDQVZNTOWYHXUSPAIBRCJ +Ring 2: ( II) AJDKSIRUXBLHWTMCQGZNPYFVOE +Ring 3: (III) BDFHJLCPRTXVZNYEIWGAKMUSQO +Ring settings: ACE +Ring positions: BDF +Reflector: (C) FVPJIAOYEDRZXWGCTKUQSBNMHL +Plugboard pair #01: AB +Plugboard pair #02: CD +Plugboard pair #03: EF +Plugboard pair #04: GH +Plugboard pair #05: IJ +Plugboard pair #06: KL +Plugboard pair #07: MN +Plugboard pair #08: OP +Plugboard pair #09: QR +Plugboard pair #10: ST +``` Notice that I redirect stdout to /dev/null so that the config is only written to -the file config. But also notice that for plugboard pair 4 I typed in `GHIJ` and -it didn't report an error. Neither did it complain about `IJ` in the next pair. -This is because it consumes input overflow. +the file config. But also notice that for [plugboard +pair](https://www.cryptomuseum.com/crypto/enigma/i/sb.htm) 4 I typed in `GHIJ` +and it didn't report an error. Neither did it complain about `IJ` in the next +pair. This is because it consumes input overflow. It shouldn't be this way for the simulator though because that could cause inconsistent number of characters expected before the text to encipher. +```sh +$ cat config +1AB2CD3EF2ABCDEFGHIJKLMNOPQRST - $ cat config - 1AB2CD3EF2ABCDEFGHIJKLMNOPQRST +$ ( cat config ; cat input ) | ./prog - 2>/dev/null +LRAVE - $ ( cat config ; cat input ) | ./prog - 2>/dev/null - LRAVE - - $ ( cat config ; cat input ) | ./prog - 2>/dev/null | ( cat config ; echo LRAVE ) | ./prog - 2>/dev/null - IOCCC +$ ( cat config ; cat input ) | ./prog - 2>/dev/null | ( cat config ; echo LRAVE ) | ./prog - 2>/dev/null +IOCCC +``` What if you don't want to worry about having to specify input but just have the settings written? You can do that too by either sending a newline or else @@ -357,144 +384,164 @@ directly type ctrl-d (or whatever you have EOF set to) or give it an empty file. The following are all equivalent in that they will write to a settings file (the first one will print a newline with the echo but that won't matter): - $ echo | ./recode -r -osettings - $ echo -n | ./recode -r -osettings - $ > empty - $ ./recode -r -osettings < empty - $ cat empty | ./recode -r -osettings - $ ./recode -r -osettings - ^D +```sh +$ echo | ./recode -r -osettings +$ echo -n | ./recode -r -osettings +$ > empty +$ ./recode -r -osettings < empty +$ cat empty | ./recode -r -osettings +$ ./recode -r -osettings +^D +``` (Above ^D was not shown but I typed it.) The way it works: if nothing is read -the buffer remains NULL and so I don't print it but still do print the settings -file. Actually even if getdelim() fails you're supposed to free the buffer so I -set another variable to indicate if it should be printed. +the buffer remains `NULL` and so I don't print it but still do print the settings +file. (Actually even if `getdelim()` fails you're supposed to free the buffer so I +set another variable to indicate if it should be printed.) # Reusing a configuration - $ echo -n|./recode -r -oconfig - 4UH5II1RJ1SPIFEJLYGZWRTBHVCAMN$ +```sh +$ echo -n|./recode -r -oconfig +4UH5II1RJ1SPIFEJLYGZWRTBHVCAMN$ - $ cat input.txt - IOCCC 2020 Enigma simulator example text file +$ cat input.txt +IOCCC 2020 Enigma simulator example text file - This is a sentence. +This is a sentence. - This is another sentence. +This is another sentence. - $ ( cat config ; cat input.txt ) | ./prog - 2>/dev/null > output - $ cat output - AAPRT 2020 Dkemny tpgnjsjai xpovrgl jvgs wxra +$ ( cat config ; cat input.txt ) | ./prog - 2>/dev/null > output +$ cat output +AAPRT 2020 Dkemny tpgnjsjai xpovrgl jvgs wxra - Fytt ly m xyiilaqh. +Fytt ly m xyiilaqh. - Ybbp ox dmuzerm oscwgytb. - $ ( cat config ; cat output ) | ./prog - 2>/dev/null > io - $ diff io input.txt - $ +Ybbp ox dmuzerm oscwgytb. +$ ( cat config ; cat output ) | ./prog - 2>/dev/null > io +$ diff io input.txt +$ +``` Alternatively you can just use the `-R` and `-f` options: - $ ./recode -finput.txt -Rconfig | ./prog - 2>/dev/null > output2 - $ diff output output2 - $ +```sh +$ ./recode -finput.txt -Rconfig | ./prog - 2>/dev/null > output2 +$ diff output output2 +$ +``` # Write config file, read data file and pass to Enigma simulator - $ ./recode -finput.txt -oconfig | ./prog - 2>/dev/null > output - Rotors: - (1) I: EKMFLGDQVZNTOWYHXUSPAIBRCJ - (2) II: AJDKSIRUXBLHWTMCQGZNPYFVOE - (3) III: BDFHJLCPRTXVZNYEIWGAKMUSQO - (4) IV: ESOVPZJAYQUIRHXLNFTGKDCMWB - (5) V: VZBRGITYUPSDNHLXAWMJQOFECK - Input rotor 1 (1 - 5): 2 - Input rotor 2 (1 - 5): 5 - Input rotor 3 (1 - 5): 3 - Input setting 1 (A - Z): C - Input setting 2 (A - Z): O - Input setting 3 (A - Z): D - Input position 1 (A - Z): E - Input position 2 (A - Z): L - Input position 3 (A - Z): O - Reflector: - (1) (B) YRUHQSLDPXNGOKMIEBFZCWVJAT - (2) (C) FVPJIAOYEDRZXWGCTKUQSBNMHL - Input reflector (1 - 2): 2 - Input plugboard pair 1: TR - Input plugboard pair 2: SN - Input plugboard pair 3: OG - Input plugboard pair 4: ME - Input plugboard pair 5: XY - Input plugboard pair 6: WZ - Input plugboard pair 7: UV - Input plugboard pair 8: AB - Input plugboard pair 9: CD - Input plugboard pair 10: FI +``` +$ ./recode -finput.txt -oconfig | ./prog - 2>/dev/null > output +Rotors: +(1) I: EKMFLGDQVZNTOWYHXUSPAIBRCJ +(2) II: AJDKSIRUXBLHWTMCQGZNPYFVOE +(3) III: BDFHJLCPRTXVZNYEIWGAKMUSQO +(4) IV: ESOVPZJAYQUIRHXLNFTGKDCMWB +(5) V: VZBRGITYUPSDNHLXAWMJQOFECK +Input rotor 1 (1 - 5): 2 +Input rotor 2 (1 - 5): 5 +Input rotor 3 (1 - 5): 3 +Input setting 1 (A - Z): C +Input setting 2 (A - Z): O +Input setting 3 (A - Z): D +Input position 1 (A - Z): E +Input position 2 (A - Z): L +Input position 3 (A - Z): O +Reflector: +(1) (B) YRUHQSLDPXNGOKMIEBFZCWVJAT +(2) (C) FVPJIAOYEDRZXWGCTKUQSBNMHL +Input reflector (1 - 2): 2 +Input plugboard pair 1: TR +Input plugboard pair 2: SN +Input plugboard pair 3: OG +Input plugboard pair 4: ME +Input plugboard pair 5: XY +Input plugboard pair 6: WZ +Input plugboard pair 7: UV +Input plugboard pair 8: AB +Input plugboard pair 9: CD +Input plugboard pair 10: FI - $ cat config - 2CE5OL3DO2TRSNOGMEXYWZUVABCDFI +$ cat config +2CE5OL3DO2TRSNOGMEXYWZUVABCDFI +``` Besides a famous book that I happen to love (who doesn't? Ah, but what is it Cody?) there's also a reference to code which I also love (just as all -participants of the IOCCC do). But what matters is the output: +participants of the IOCCC do). Other things there don't mean anything but what +does is the output: - $ cat output - DBFAF 2020 Ittejg ltblwriac uqdfqvr dhqh ghhf - Jsjy ce v pxdmullo. +```sh +$ cat output +DBFAF 2020 Ittejg ltblwriac uqdfqvr dhqh ghhf - Sara tj rtaayak uxfhjcti. +Jsjy ce v pxdmullo. - $ ./recode -Rconfig -foutput | ./prog - 2>/dev/null - IOCCC 2020 Enigma simulator example text file +Sara tj rtaayak uxfhjcti. - This is a sentence. +$ ./recode -Rconfig -foutput | ./prog - 2>/dev/null +IOCCC 2020 Enigma simulator example text file - This is another sentence. +This is a sentence. +This is another sentence. + +``` # Piping directly to the Enigma code once (with randomised settings, saved) This is like the above only randomised: - $ ./recode -r -oconfig|./prog - 2>/dev/null - IOCCC - UGEVP +```sh +$ ./recode -r -oconfig|./prog - 2>/dev/null +IOCCC +UGEVP +``` -Note that I typed in IOCCC and sent EOF (ctrl-d); the settings were written to +Note that I typed in `IOCCC` and sent `EOF` (ctrl-d); the settings were written to the config file (for deciphering later) and then all of it was piped to the Enigma entry resulting in the line below IOCCC. But let's verify it worked out okay: - $ cat config - 2BM4GJ3HK1LNCBXWRMGKSYIAZUTPVJ +```sh +$ cat config +2BM4GJ3HK1LNCBXWRMGKSYIAZUTPVJ +``` Without having to copy/paste intermediate results: - $ echo IOCCC | ./recode -Rconfig | ./prog - 2>/dev/null | ./recode -Rconfig | ./prog - 2>/dev/null - IOCCC +```sh +$ echo IOCCC | ./recode -Rconfig | ./prog - 2>/dev/null | ./recode -Rconfig | ./prog - 2>/dev/null +IOCCC +``` You can also use a string for the `-R` option. I'll use command substitution and actual pasting to demonstrate: - $ echo IOCCC | ./recode -R$(cat config) | ./prog - 2>/dev/null | ./recode -R2BM4GJ3HK1LNCBXWRMGKSYIAZUTPVJ | ./prog - 2>/dev/null - IOCCC +```sh +$ echo IOCCC | ./recode -R$(cat config) | ./prog - 2>/dev/null | ./recode -R2BM4GJ3HK1LNCBXWRMGKSYIAZUTPVJ | ./prog - 2>/dev/null +IOCCC +``` # Usage conclusion -That should give you an idea of how to use the recode program. I leave it as +That should give you an idea of how to use the `recode` program. I leave it as an exercise to the reader to implement additional features but here are some ideas of what could be done and how this entry might be used (including that delicious challenge). # Example additions -* Add code (to prog.c) that tries to determine possible decipherments based on +* Add code (to [prog.c](prog.c)) that tries to determine possible decipherments based on a given crib (or set of cribs). # Example uses @@ -515,19 +562,21 @@ anyway? * Best idea: try the below experiment! -# Delicious Enigmatic: Double-layered Chocolate Fudge Cake +# Deliciously Enigmatic: Double-layered Chocolate Fudge Cake -As I was making the above silly list something occurred to me. My other entries -this year include a recipe for a wonderful double-layered chocolate fudge cake -but why would it not be included in this one too? But then if that's the case -why on Earth should it be unscrambled? +As I was making the above silly list something occurred to me. My [other +entry](/2020/ferguson1/prog.c) this year includes a recipe for a wonderful +double-layered chocolate fudge cake but why would it not be included in this one +too? But then if that's the case why on Earth should it be unscrambled? So this is what I offer: if you take one of the settings below and run the simulator on the file [chocolate-cake.html][] you will have a wonderful chocolate cake recipe (that even my late stepmum who didn't even like chocolate loved - it's a speciality of my mum's and they were the best of friends too). If -you're lazy just go and look at my other entry. Then again if you're lazy you're -probably not reading this far! :) +you're lazy (or just want some delicious double-layered chocolate fudge cake!) +just go and look at the [recipe](../ferguson1/chocolate-cake.html) (or +[here](../ferguson1/chocolate-cake.md) if on GitHub) in my other entry. Then +again if you're lazy you're probably not reading this far! :) The settings is one of the below but a couple questions you might ask yourself: @@ -536,13 +585,16 @@ The settings is one of the below but a couple questions you might ask yourself: 2. Is there some other kind of trickery involved here? I can think of the best way to answer these and I think I need not even mention -it. Have fun and enjoy! BTW: Depending on where you are in this world and how -warm it is the icing can be a bit of an issue - I give some ideas in the file on -what can be done for this. At worst though the icing won't come out as good as -it usually does. +it. Have fun and enjoy! + +BTW: Depending on where you are in this world and how warm it is the icing can +be a bit of an issue - I give some ideas in the file on what can be done for +this. At worst though the icing won't come out as good as it usually does. +That's assuming you follow in the instructions exactly as they are; it's a very +picky recipe. -Hints: +## Hints: 1. It's not the middle one. @@ -557,6 +609,7 @@ this way? (I think the second answer is 'no' but that's me.) 4. The above points might or might not be relevant. What is relevant is one will reveal a wonderful [Double-layered Chocolate Fudge Cake][] recipe: +``` 142CHOCOLATESVCAKESTBJLKMUMVWX 0EZ4PC1CC0PGTAQSOXWNMDRYKFUZEI 3UY0XF4QG1GTJQLARPKHBEMCOFVUIN @@ -573,7 +626,7 @@ will reveal a wonderful [Double-layered Chocolate Fudge Cake][] recipe: 4MU1MS3CA0KECHOLATBJSNPXVUFGZY 4VW0SL1YB0IYJSLBECKTNAXGPUVHRF 0MC4OH2CO1LATEUMBJCDFGHINOPRQS - +``` BTW: What's the middle of a list with even numbered items anyway? diff --git a/all/.gitignore b/all/.gitignore new file mode 100644 index 000000000..d332be6d3 --- /dev/null +++ b/all/.gitignore @@ -0,0 +1,3 @@ +1*/ +2*/ +3*/ diff --git a/all/summary.txt b/all/summary.txt index e6ddbe2e9..36fbbd275 100644 --- a/all/summary.txt +++ b/all/summary.txt @@ -1,4 +1,4 @@ -# yr filename Spoiler summary +# yr entry Spoiler summary # 1984 anonymous prints hello world, where read is write diff --git a/bin/sgit b/bin/sgit index fb68f2d47..f865948b0 100755 --- a/bin/sgit +++ b/bin/sgit @@ -5,28 +5,33 @@ # # This script allows one to run sed under git control without having to come up # with a list of files first and then passing those to the command. +# # It allows for multiple sed commands and multiple globs. By default it uses -i -# to edit the file in place (without backup extension) but this can be -# overridden with the -I option. See -h option for all the options. +# to edit the file in place (WITHOUT BACKUP EXTENSION; use -i option if you want +# a backup!) but in place editing can be overridden with the -I option. See -h +# option for all the options. # # DISCLAIMER AND WARNING: this is something of a hack and might be error prone. # It works for what is needed but possibly could be improved. Even so I like it -# how it is and I don't think it would do good to add any additional features -# except perhaps allowing for one to specify path to sed. +# how it is and I don't think it would do much good to add many more additional +# features. # # - Cody Boone Ferguson (@xexyl) # -export SGIT_VERSION="0.0.7-1 12-04-2023" # format: major.minor.patch-release DD-MM-YYYY +export SGIT_VERSION="0.0.8-1 19-04-2023" # format: major.minor.patch-release DD-MM-YYYY -USAGE="usage: $(basename "$0") [-h] [-V] [-v level] [-x] [-I] [-o sed_options] [-s sed] [-e command] +USAGE="usage: $(basename "$0") [-h] [-V] [-v level] [-x] [-I] [-i extension] [-o sed_options] [-s sed] [-e command] -h print help and exit -V print version and exit -v level set verbosity level -x turn on tracing (set -x) -I disable in place editing - -o sed options (don't pass '-') + -i extension set backup extension (default none) + WARNING: sed -i overwrites existing files + WARNING: this will create another file for each file changed + -o sed options (NOTE: don't pass '-'!) WARNING: use of '-o n' without '-I', can depending on command, empty files -s sed set path to sed -e command append sed command to to list to execute on globs @@ -38,6 +43,7 @@ export SED export SED_OPTIONS="" export I_FLAG= export VERBOSITY=0 +export EXTENSION="" # we need an array for sed commands declare -a SED_COMMANDS @@ -47,7 +53,7 @@ IFS=$'\t\n' # parse args # -while getopts :hVv:xIo:s:e: flag; do +while getopts :hVv:xIi:o:s:e: flag; do case "$flag" in h) echo "$USAGE" 1>&2 exit 2 @@ -61,6 +67,8 @@ while getopts :hVv:xIo:s:e: flag; do ;; I) I_FLAG="-I" ;; + i) EXTENSION="$OPTARG" + ;; o) SED_OPTIONS="-$OPTARG" ;; s) SED="$OPTARG" @@ -148,6 +156,12 @@ if [[ "$VERBOSITY" -gt 1 ]]; then echo "debug[2]: looping through all globs" 1>&2 fi +if [[ -n "$EXTENSION" ]]; then + if [[ "$VERBOSITY" -ge 1 ]]; then + echo "debug[1]: using backup extension: $EXTENSION" 1>&2 + fi +fi + GLOBS="$#" i=0 while [[ "$i" -lt "$GLOBS" ]]; do @@ -155,12 +169,13 @@ while [[ "$i" -lt "$GLOBS" ]]; do echo "debug[2]: found glob: $i" 1>&2 fi + if [[ "$VERBOSITY" -ge 1 ]]; then if [[ -z "$I_FLAG" ]]; then if [[ -n "$SED_OPTIONS" ]]; then - echo "debug[1]: about to run: git ls-files $1 | xargs $SED -i\"\" $SED_OPTIONS ${SED_COMMANDS[*]}" 1>&2 + echo "debug[1]: about to run: git ls-files $1 | xargs $SED -i\"$EXTENSION\" $SED_OPTIONS ${SED_COMMANDS[*]}" 1>&2 else - echo "debug[1]: about to run: git ls-files $1 | xargs $SED -i\"\" ${SED_COMMANDS[*]}" 1>&2 + echo "debug[1]: about to run: git ls-files $1 | xargs $SED -i\"$EXTENSION\" ${SED_COMMANDS[*]}" 1>&2 fi else if [[ -n "$SED_OPTIONS" ]]; then @@ -173,9 +188,9 @@ while [[ "$i" -lt "$GLOBS" ]]; do if [[ -z "$I_FLAG" ]]; then if [[ -n "$SED_OPTIONS" ]]; then - git ls-files "$1" | xargs "$SED" -i"" "$SED_OPTIONS" "${SED_COMMANDS[@]}" + git ls-files "$1" | xargs "$SED" -i"$EXTENSION" "$SED_OPTIONS" "${SED_COMMANDS[@]}" else - git ls-files "$1" | xargs "$SED" -i"" "${SED_COMMANDS[@]}" + git ls-files "$1" | xargs "$SED" -i"$EXTENSION" "${SED_COMMANDS[@]}" fi else if [[ -n "$SED_OPTIONS" ]]; then diff --git a/bin/sgit.README.md b/bin/sgit.README.md index e3d716076..32f6e4c54 100644 --- a/bin/sgit.README.md +++ b/bin/sgit.README.md @@ -7,36 +7,71 @@ efficiency because it ran git ls-files for each `sed` command. Now it is a bit more thorough and is more efficient (though not perfect). It allows you to specify a path to `sed`, `sed` options and multiple `sed` commands -(though this always existed). The default behaviour is to use in place editing -**WITHOUT A BACKUP EXTENSION** but you may override the saving to disk with the -`-I` option. +(though this always existed). The _default_ behaviour is to use in place editing +(**WITHOUT A BACKUP EXTENSION**; use `-i` to provide a backup extension) but you +can override the saving to disk with the `-I` option. ## Usage ```sh -usage: sgit [-h] [-V] [-v level] [-x] [-I] [-o sed_options] [-s sed] [-e command] +usage: sgit [-h] [-V] [-v level] [-x] [-I] [-i extension] [-o sed_options] [-s sed] [-e command] -h print help and exit -V print version and exit -v level set verbosity level -x turn on tracing (set -x) -I disable in place editing - -o sed options (don't pass '-') + -i extension set backup extension (default none) + WARNING: sed -i overwrites existing files + WARNING: this will create another file for each file changed + -o sed options (NOTE: don't pass '-'!) WARNING: use of '-o n' without '-I', can depending on command, empty files -s sed set path to sed - -e command append sed command to execute on globs - -sgit version: 0.0.7-1 12-04-2023 + -e command append sed command to to list to execute on globs +sgit version: 0.0.8-1 19-04-2023 ``` You **MUST** specify at least one `sed` command and one glob: the sed command by way of the `-e` option (just like with `sed`); anything after the last option is a glob. You may specify more than one of each. Specify `-e` for each command. +# A note about the `-i` option and backup extensions + +It works like `sed -i` except that the default behaviour of the script is to use +`-i` just with an empty backup extension (this is required for some versions of +`sed` which force that a backup extension actually be provided with the `-i` +option .. I'm looking at you, BSD/macOS `sed`). + + +# `-i` WARNING: each file edited will result in another file in the working directory + +Of course if you have 50 files that are affected then 50 new files will be +created. + +# `-i` WARNING: `sed -i` **WILL OVERWRITE EXISTING FILES**! + +Please be aware that if a backup file already exists it **WILL** be overwritten! +I won't even try and detect this because it's not how `sed` works and it would +overly complicate the script. + + +# `-o n` WARNING: invalid use of -o n can empty files! + +Because `sed -n` does not print output if you do not use `-I` and you use +substitute you can empty the entire file. For instance **DO NOT** do this: + + +```sh +./sgit -o n -e 's/.//g' sgit +``` + +because it would empty `sgit`! + + # Examples -## Change in this file (in memory only) `\` to be `used` but only show lines changed: +## Change in this file (_IN MEMORY ONLY_) `\` to `used` but only show lines changed: ```sh ./sgit -I -o n -e 's/\/used/p' README.md @@ -53,38 +88,69 @@ needs to be: ./sgit -I -o n -e '/\/p' . ``` -## Change references of `\` to be `used` in this file and save it: +## With tracing enabled, change references of `\` to `used` in this file and save it: ```sh -./sgit -e 's/\/used/p' -v3 -x README.md +./sgit -e 's/\/used/g' -x README.md ``` -## Change `\` to `used` but only if it's on the third line + +## With tracing enabled, change references of `\` to `used`, duplicating the lines, in this file and save it: ```sh -./sgit -e '3s/\/used/g' README.md +./sgit -e 's/\/used/p' -x README.md + +``` + +## Verbosely (level 1) change references of `\` to `used` in this file and save it: + +```sh +./sgit -e 's/\/used/g' -v1 README.md + +``` + +## Verbosely (level 3) change references of `\` to `used` in this file with a backup as `README.md.bak` + +```sh +./sgit -i.bak -e 's/\/used/g' -v3 README.md + +``` + +With that you would see something like: + +```sh +debug[2]: sed commands: -e s/\/used/g +debug[2]: looping through all globs +debug[1]: using backup extension: .bak +debug[2]: found glob: 0 +debug[1]: about to run: git ls-files README.md | xargs /opt/local/bin/sed -i".bak" -e s/\/used/g +debug[2]: 0 remaining globs +``` + +Level 2 would not show how many globs remain after each operation. + + +## Change `\` to `used` but only if it's on the first line + +```sh +./sgit -e '1s/\/used/g' README.md ``` Alternatively you could do one of: ```sh -./sgit -e '3s/\/u&/g' README.md -./sgit -e '3s/\(\\)/u\1/g' README.md +./sgit -e '1s/\/u&/g' README.md +./sgit -e '1s/\(\\)/u\1/g' README.md ``` -# WARNING: invalid use of -o -n can empty files! - -Because `sed -n` does not print output if you do not use `-I` and you use -substitute you can empty the entire file. For instance **DO NOT** do this: - +## Change `\` to `crack` but only if it's on the third line ```sh -./sgit -o n -e 's/.//g' sgit +./sgit -e '3s/\/crack/g' README.md ``` -because it would empty `sgit`! ## Installation diff --git a/bugs.md b/bugs.md index 7d6020bc1..a3f819a4d 100644 --- a/bugs.md +++ b/bugs.md @@ -11,7 +11,11 @@ The following is a known list of **BUGS and (mis)FEATURES** in IOCCC winners. Can you fix/improve entries not under the INABIAF (it's not a bug it's a feature)? You are **VERY WELCOME** to try. -Please submit your fixes in a [GitHub pull +NOTE: currently this file is mostly for us. We are not yet ready for help except +for dead links and missing files. We will remove this notice when this changes. +We will note this below for each status we're not yet ready for help with. + +As far as how to help: please submit your fixes in a [GitHub pull request](https://github.com/ioccc-src/temp-test-ioccc/pulls) (with ONE PULL REQUEST *PER* FIX, please)! @@ -36,6 +40,12 @@ it takes away some instructional value or even usability. _In this case we're judgement but invariably some might have been the wrong decision. Thank you for understanding! +I ([Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson)) +accept the blame in some cases; when working on getting entries to compile +sometimes I got carried away with it and there might be that I fixed some things +that should not have been fixed. I am correcting these mistakes as I come across +them but if I miss any please let the judges or me know. + ### ON **ALL** FIXES / IMPROVEMENTS / CHANGES @@ -68,6 +78,11 @@ Again, THANK YOU! # LIST OF STATUSES - PLEASE READ BEFORE FIXING (you may skip if you're only interested in knowing about entries with known issues) +NOTE: when going through the entries you can skip to the next entry (some are +detailed explanations) by searching for `^## STATUS:` in your editor (or +searching for it - probably without the `^` in your browser). For a specific +year try `^# YYYY` where `YYYY` is the year as a number. + Entries below have one or more of the following _**STATUS**_ values. Please see the text below for more information. If an entry has more than one status it means that either they all apply or they compliment each other. For instance @@ -79,8 +94,9 @@ resolving these issues and has fixed many but you're welcome to have a go at it too (though he'll be very sad if he doesn't have a chance to at first fix it :-( so you might want to hold off for now :-) .. or not :-) ). He hopes to have most of the remaining entries resolved in the near future but nevertheless if you're -okay making people very sad you may have a go at the entries :-) He'll remove -this part later on. +okay making people very sad you may have a go at the entries :-) [Yusuke +Endoh](/winners.html#Yusuke_Endoh) has also fixed a number of entries though at +this point he does not know it. :-) Cody will remove this part later on. ## General notes about the statuses and making fixes @@ -107,28 +123,60 @@ segfault in macOS of [1989/paul](1994/paul/paul.c): changing the `int *` to a But even if they are fixable (which will likely be hard to do) it's almost certain that such code would be just as non-portable (importable ? :-) ). +In rare cases they are valid. For instance Cody noticed in linux the following +warning in [1985/applin](1985/applin/applin.c) with gcc: + +``` +applin.c:1:78: warning: incompatible implicit declaration of built-in function 'execlp' [-Wbuiltin-declaration-mismatch] + 1 | main(v,c)char**c;{for(v[c++]=strdup("Hello, world!\n");(!!c)[*c]&&(v--||--c&&execlp(*c,*c,c[!!c]+!!c,!c));**c=!c)write(!!*c,*c,!!**c);} + | ^~~~~~ +``` + +and this reminded him of his fix to +[1984/anonymous](1984/anonymous/anonymous.c). In the case of `1984/anonymous` it +was a bit more involved but with `1985/applin` one need only add to the Makefile +`-include unistd.h`. So there are some cases where fixing warnings can fix a +problem but in general they should be ignored even if they're annoying. + Hopefully with the example entries listed above you get the idea. +### General request on original code: + +If you're fixing an entry please make as _FEW CHANGES AS POSSIBLE_! This is to +make it as close to the original but allowing it to work. This might be less of +a problem when providing alternate versions but it might still be nice to have +it as close as possible to the original. See also below two points. + ### Request for one-liners: -For one-liners please keep the file one line if at all possible! If it needs an +For one-liners _PLEASE KEEP THE FILE ONE LINE IF AT ALL POSSIBLE_! If it needs an include you can update the Makefile `CINCLUDE` variable. For instance if it needs `stdio.h` you could do `-include stdio.h`. Please leave a space after the -`=` in the Makefile and thank you! +`=` in the Makefile. You may also have extra long lines if this seems useful to +make it a one-liner even if it kind of makes it longer than what the judges +consider a one-liner. Thank you! -### On layout of program source +### On layout of program source: -If you make changes PLEASE TRY and keep the source code layout as close to the -original as possible. This might not always be possible and if you have an +If you make changes _PLEASE TRY AND KEEP THE SOURCE CODE LAYOUT AS CLOSE TO THE +ORIGINAL AS POSSIBLE_. This might not always be possible and if you have an editor that does formatting it can cause problems. Sometimes formatters can even break code! [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) has experienced this many times with vim so he tends to disable all format options -when formatting code. +when formatting code. In vim you should be able to do that with: + +``` +:set formatoptions= +``` + ## STATUS: known bug - please help us fix +NOTE: we're still locating entries and working on fixes with this status so we're not yet +ready for help. We will remove this when we are. + Entries with this status have one or more bugs that need to be fixed. Are you able to fix it? We welcome your help! @@ -139,17 +187,36 @@ careful judgement when fixing bugs please! ## STATUS: possible bug (possibly depending on system) - please help test and if necessary fix +NOTE: we're still locating entries and working on fixes with this status so we're not yet +ready for help. We will remove this when we are. + Entries with this status might or might not have a bug possibly depending on the system. In these entries we don't have the appropriate systems to test and fix any problems. +## STATUS: probable bug (possibly depending on system) - please help test and if necessary fix + +NOTE: we're still locating entries and working on fixes with this status so we're not yet +ready for help. We will remove this when we are. + +Entries with this status almost certainly have a bug or some other problem. The +issue or issues might depend on the system much like the above _STATUS: possible +bug (possibly depending on system)_. + + ## STATUS: doesn't work with some platforms - please help us fix +NOTE: we're still locating entries and working on fixes with this status so we're not yet +ready for help. We will remove this when we are. + Entries with this status do not work under some OSes and/or architectures (and/or something else?). Please help us to fix it! ## STATUS: doesn't work with some compilers - please provide alternative code +NOTE: we're still locating entries and working on fixes with this status so we're not yet +ready for help. We will remove this when we are. + Some entries do not work with some compilers. A good example is [1992/lush](1992/lush/lush.c) which uses error messages from the compiler to generate its output. @@ -158,12 +225,18 @@ Please help us by writing alternative code! ## STATUS: main() function args not allowed - please help us fix +NOTE: it appears that all of these have been fixed. However some still have +problems. This is what the status means, however: + Entries with this status have a problem in that the args to main() are not of a -specific type due this being allowed in earlier C. This shows itself in some -compilers like clang. [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) -looked at the source code of clang and reported that there is no way to override -this requirement so these entries will fail to compile with clang. That's why he -in some entries he fixed he did it by adding a function called `pain()`. :-) +specific type due to this being allowed in earlier C. Some compilers like clang +have a deficiency where they do not allow this so these entries do not work with +clang. + +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) looked at the source +code of clang and reported that there is no way to override this requirement so +these entries will fail to compile with clang. That's why in some entries he +fixed he did it by adding a function called `pain()`. :-) **NOTE for macOS users**: please be aware that _gcc_ under macOS **is actually clang** despite the fact it might appear to be gcc: no symlink and both gcc and @@ -181,6 +254,9 @@ with compilers that are less strict. ## STATUS: compiled executable crashes - please help us fix +NOTE: we're still locating entries and working on fixes with this status so we're not yet +ready for help. We will remove this when we are. + While such entries can compile, the resulting executable sometimes or always crashes. @@ -189,34 +265,49 @@ not mutually exclusive in some cases). ## STATUS: uses gets() - change to fgets() if possible (in some cases getline() works) +NOTE: we're still locating entries and working on fixes with this status so we're not yet +ready for help. We will remove this when we are. + Entries with this status use `gets()` which is unsafe because it has no limit on the length of the string. [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) has fixed several of these and he's -working on others in between fixing other things. He provides some important -notes: +working on others in between fixing other things. -First: in some cases changing the entry to use `fgets()` will break the entry -and in some cases cause it to crash. Where this is known we will document it. -Some of these Cody is also working on. +There's a very good reason for this even though it is bordering on tampering +entries: in modern systems one will get possibly alarming and certainly annoying +warnings during at least one of compiling, linking and execution. In macOS it's +most annoying as it happens during execution (also compilation) with the warning +being interspersed with the output of the program, often causing confusing +output with the entry. A good example that was fixed is +[1990/tbr](1990/tbr/tbr.c). -Second: you MUST check the output before and after to make sure that it remains +Cody provided some important notes on this status with respect to fixing / +changing entries: + +0. In some cases changing the entry to use `fgets()` will break the entry and in +some cases cause it to crash. Where this is known we will document it. Some of +these Cody is also off and on working on. + +1. You **MUST** check the output before and after to make sure that it remains the same. Sometimes the output might not be immediately obviously wrong but is. -We will document known examples. +We will document known examples as we come across them. -Third: `gets()` does NOT STORE the `'\n'` but `fgets()` DOES! This is one of the +2. `gets()` does NOT STORE the `'\n'` but `fgets()` DOES! This is one of the reasons some of the entries break when changed to `fgets()`. Cody has fixed some -of these but there are others he hasn't had time to address and/or even discover +of these but there are others he hasn't had time to address or even discover yet. -Fourth: just because you don't see the string `gets` in the code does not mean -it's not used. It is after all the Obfuscated C Code Contest! :-) Sometimes it -will be in the Makefile and other times it will be obfuscated in other ways. -Compilers and linkers tend to warn about its use and this is a good way to find -entries that use it even if it's not visible in the code. +3. Just because you don't see the string `gets` in the code does not mean it's +not used. It is after all the International _Obfuscated C Code_ Contest! :-) +Sometimes it will be in the Makefile and other times it will be obfuscated in +other ways. Compilers and linkers tend to warn about its use (and as noted in +macOS it also happens at execution) and this is a good way to find entries that +use it even if it's not visible in the code. -NOTE: this status is not necessarily mutually exclusive with the INABIAF (it's a -bug not a feature) status. The reason for this is due to warnings during linking -or runtime, sometimes causing confusing output. +_NOTE_: this status is _NOT necessarily mutually exclusive_ with the _INABIAF_ (it's a +bug not a feature) status. The reason for this is due to warnings during +compiling, linking and/or runtime, sometimes causing confusing output (as noted +above). ## STATUS: missing file(s) - please provide them @@ -232,13 +323,30 @@ In these entries one or more make rules noted by the author and/or judges is/are missing. You might consider looking at the [archive](/archive) as a good place to find them. +## STATUS: missing or dead link - please provide them + +This is as they sound: a link is either missing or it's no longer valid. In many +cases the [Internet Wayback Machine](https://web.archive.org) will be very +useful but there happens to be numerous links that this is not helpful. In other +cases the URL has changed. Some of these have been discovered by the Internet +Wayback Machine with the orange status. + +### Statuses of Internet Wayback Machine archive: + +- Green (3xx): redirect (this has been used to find changes in URL). +- Orange (4xx): not found etc. +- Blue: this is a good link (but note that this doesn't mean that it's correct!). + +The archive website will tell you if the link was never captured. + ## STATUS: INABIAF - please **DO NOT** fix ### INABIAF: It's not a bug it's a feature :-) Entries with this status should NOT be touched (unless they have another status -that suggests that issue can be changed): they are system specific by design -or are other things that are not actually bugs even if they appear to be. But -are noteworthy nonetheless. +that suggests that _that_ issue can be changed): they are system specific by +design or are other things that are not actually bugs or bugs even if they +appear to be. Or they might be documented bugs or things that simply are part of +the entry. Nonetheless they are noteworthy. NOTE: the definition of this status changed over time. At one point it was when something was noted by the author, the judges, a consequence of earlier @@ -248,7 +356,8 @@ appear to be buggy. An example of system specific entries: [1984/mullender](1984/mullender/mullender.c) (see below and the [faq](/faq.md) for a version that works in modern systems) is very system specific and was before system specific winning entries were discouraged. This is an all time -personal favourite of Landon Curt Noll. +personal favourite of Landon Curt Noll. Run the alternate code to understand why +this might be (along with how strange the source code is :-) ). An example where a crash is not a bug: [2019/endoh](2019/endoh/endoh.c) is supposed to crash. There are others that are also supposed to crash or that are @@ -256,8 +365,8 @@ known to segfault but are considered features. As of 10 April 2023 the definition changed for a second time (the first time was 07 April 2023). If something is noted by the author as a known bug or limitation -it need not be fixed unless it impacts the usability of the program or removes -instructional value. An example where a crash undocumented needn't be fixed is +it need not be fixed **unless it impacts the usability** of the program or **it removes +instructional value**. An example where a crash undocumented needn't be fixed is [1984/laman](1984/laman/laman.c). On the other hand the fixes made by [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) in [1990/theorem](1990/theorem/theorem.c) were useful. @@ -265,18 +374,18 @@ Boone Ferguson](/winners.html#Cody_Boone_Ferguson) in Nonetheless we challenge you to fix these entries for educational/instructional value and/or enjoyment but we kindly request that you **DO NOT** submit a pull request! If you can't figure it out you're invited to look at the git diffs, -where there are some (some were fixed earlier on but rolled back due the fix -feeling like tampering). +where there are some (some were fixed earlier on but rolled back as both Cody +and Landon individually felt that the fix was tampering with the entry). NOTE: in the case of `gets()` we've fixed some to avoid the warning of the -compiler, linker or even during runtime, depending on the system. In [one -case](1990/tbr/tbr.c) the fix actually prevents confusing output (though that -was not the only fix made). +compiler, linker or even during runtime, depending on the system. In [some cases +like 1990/tbr](1990/tbr/tbr.c) the fix actually prevents confusing output (though that +was not the only fix made in that entry). ### Exception: your own entries -Of course if you're the author you're welcome to fix your own entry (or else -suggest that they're fixed)! +Of course if you're the author you're welcome to fix your own entry, prefer your +own fix or suggest that they're fixed! ## STATUS: requires a compiler supporting `-traditional-cpp` - alternate code requested @@ -295,10 +404,12 @@ compiler supporting you are welcome to summit such code via a will be happy to credit you in the entry's _README.md_ file. NOTE: as of commit fa8a9b8b28a6b69a6b4efd74a45402f745e280b3 we believe that all -the entries with this problem have been fixed. +the entries with this problem have been fixed due [Cody Boone +Ferguson](/winners.html#Cody_Boone_Ferguson)'s pursuit in fixing entries. Thanks +Cody! -# List of entries by year, sorted in alphabetical order +# List of entries by year, sorted in alphabetical order per year # 1984 @@ -310,17 +421,6 @@ arg. # 1985 -## [1985/applin](1985/applin/applin.c) ([README.md](1985/applin/README.md) -## STATUS: doesn't work with some platforms - please help us fix - -[Yusuke Endoh](/winners.html#Yusuke_Endoh) provided a fix for gcc but -[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) observed that this does -not work under macOS. It prints `H????????` with additional `?`s printed as it -continues to run. - -We have not had a chance to try and fix this yet but you're welcome to have a go -at it. - # 1986 @@ -542,6 +642,23 @@ This will be fixed in time but it's noted here for now. # 1991 +## [1991/dds](1991/dds/dds.c) ([README.md)(1991/dds/README.md)) +## [1991/dds.alt](1991/dds/dds.alt.c) ([README.md)(1991/dds/README.md)) +## STATUS: INABIAF - please **DO NOT** fix + +If the BASIC file cannot be opened for reading or the output file cannot be +opened for writing the program will crash. This is not a bug but a feature. +Please do not fix this except for the challenge. + +Please also note that for `clang` you have to use [dds.alt](1991/dds/dds.alt.c) not +[dds.c](1991/dds/dds.c). + +## STATUS: uses gets() - change to fgets() if possible + +That being said the compiled code uses `gets()` not `fgets()`. Can you fix this? +You might find that the `s` array is relevant but if you do change it please +make sure to test all functionality! + ## [1991/westley](1991/westley/westley.c) ([README.md](1991/westley/README.md)) ## STATUS: INABIAF - please **DO NOT** fix @@ -553,6 +670,7 @@ Please don't try and fix it as it's not a bug and was actually documented as a possibility. Can you find out how? + # 1992 ## [1992/buzzard.1](1992/buzzard.1/buzzard.1.c) ([README.md](1992/buzzard.1/README.md)) @@ -589,6 +707,12 @@ else. This should NOT be fixed. # 1994 +## [1994/horton[(1994/horton/horton.c) ([README.md](1994/horton/README.md)) +## STATUS: INABIAF - please **DO NOT** fix + +If not enough args are specified this program will likely crash or do something +else. This should NOT be fixed. + ## [1994/ldb](1994/ldb/ldb.c) ([README.md](1994/ldb/README.md)) ## STATUS: known bug - please help us fix @@ -726,8 +850,636 @@ some invalid prototypes and use `printf()` instead of the invalid pointer to it compilation error or crash. +## [1995/vanschnitz](1995/vanschnitz/vanschnitz.c) ([README.md](1995/vanschnitz/README.md)) +## STATUS: missing file - please provide it + +The authors stated that they included a version that allows people with just K&R +compilers to use the program but this file is missing. Can you provide it? + +We would appreciate anyone who has it or even just knows the name! Thank you. + + # 1996 +## [1996/august](1996/august/august.c) ([README.md](1996/august/README.md)) +## STATUS: doesn't work with some compilers - please provide alternative code + +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed a segfault in +this program that prevented it from working but he observes that this hangs +in macOS with this invocation in particular: + +```sh +cat august.c august.oc | ./august > august.oo +``` + +This happens to do with the fact that macOS is `clang` even the binary `gcc`. +Trying clang in linux and the same problem occurs. As well if specifying (even +with gcc) certain flags this also happens namely `-ggdb3`. The bug fix involved +increasing the value of `Z` as it was accessing way out of range of the array, +thus causing a segfault. + +The compilation should look like: + +```sh +cc -std=gnu90 -Wall -Wextra -pedantic -Wno-error -Wno-implicit-function-declaration -Wno-invalid-source-encoding -Wno-invalid-utf8 -DZ=240000 -D'T=m[s]' -D'P=m[s++]' -D'L=m[p++]' -D'g=getchar()' -DE=else -DW=while -D'B=m[p++]' -DI=if -DR='s=s+l/2;T=r;I(l%2)s++' -D'X=m[s-' -D'D=Q(13,-)Q(14,*)Q(15,/)Q(16,%)Q(6,==)Q(7,!=)Q(8,<)C(1,r=P;m[T]=r;T=r)C(9,r=P;m[T]=r;s++)' -O3 august.c -o august +``` + +but again this will not work with clang. As the judges noted that some compilers +compile it into an infinite loop I'm (Cody) inclined to believe that this is the +source of the problem. + +Nevertheless if you have a fix for clang we welcome it! + + +## [1996/gandalf](1996/gandalf/gandalf.c) ([README.md](1996/gandalf/README.md)) +## STATUS: missing or dead link - please provide them + +The link was http://www.tc3.co.uk/~gandalf/G.HTML but this no longer exists as +it was instead requiring a login / password. + +Do you have an updated link? We welcome your help! + +## [1996/jonth](1996/jonth/jonth.c) ([README.md](1996/jonth/README.md)) +## STATUS: doesn't work with some platforms - please help us fix + +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) noted that this does +not work properly in macOS (at least Ventura). He did some debugging and has +determined where the crash occurs (depending on invocation of the program) and +came up with a workaround of sorts but if you have a fix we welcome your help. + +With this you'll need XQuartz as described in the [faq](faq.md) and the +[1996/jonth/README.md](1996/jonth/README.md) file. + +Notes from Cody: + +Depending on invocation it appeared to have more than one crash location. It +appears that the correct invocation might be `./jonth :0 :0` but it still +crashes. Earlier invocations it would crash at + +```c +s=XDefaultScreen(V=d[D]=XOpenDisplay(*(h+=!! *h))); +``` + +because `XOPenDisplay()` returned NULL. But using `:0 :0` _appears_ to resolve +that problem. However instead it crashes at this code: + +```c +XMapRaised(V,R[D][x][y]=w(V,e,H*x,H*y,H,H,1,0,1,0,2048,&c)); +``` + +This is formed through the macros `K` and what appears to be `S` (but maybe +others?): + +```c +#define K Y(o,XMapRaised(V,e);)x=3;x--;)for(y=3;y--;r(G))XMapRaised(V,R[D] +#define S +k),z(k-P=w(V,e,H*x,H*y,H,H,1,0,1,0,2048,&c));}XEvent J;M(){XFlush( +``` + +and the code surrounding it will look something like: + +```c +for (o[D]=XCreatePixmapFromBitmapData(V,e,b,H,H,BlackPixel(V,s), + WhitePixel(V,s),DefaultDepth(V,s)),memset(b,x=0,H*H); x 40 Window ww = w(V,e,H*x,H*y,H,H,1,0,1,0,2048,&c); + 41 XMapRaised(V,R[D][x][y]=ww); + 42 } + +``` + +...so it never reaches the call that should be using its return value. +Unfortunately if XQuartz has debug symbols I don't have access to them so I'm at +a loss at this time. + +A C pre-processed version of the code is below in case this helps you find the +problem: + +```c +#include +#include +extern XIM Z;XID(*w)()=XCreateWindow,m,e,o[2],W[2],G[2],R[2][3][3];Display*V,*d[2];char**h,k=25,b[2500],H=50,D,s,x,y,i;T(){float l;XSetWindowAttributes c;s=XDefaultScreen(V=d[D]=XOpenDisplay(*(h+=!! *h)));XStoreName(V,e=w(V,RootWindow(V,s),0,0,152,152,2,0,1,0,0,0),"II"+D);for(G[D]=XCreatePixmapFromBitmapData(V,e,b,H,H,BlackPixel(V,s),WhitePixel(V,s),DefaultDepth(V,s)),memset(b,x=0,H*H);xH||z(x+i,(z(H-x-i,x),x)))x20&&l>x;l-=.5)z(x+k,y=sqrt(l*l-x*x) +k),z(k-x,y)-z(y,x+k)+z(y,k-x)*z(x+k,y=H-y),z(k-x,y),z(y,k-x),z(y,k+x);for(o[D]=XCreatePixmapFromBitmapData(V,e,b,H,H,BlackPixel(V,s),WhitePixel(V,s),DefaultDepth(V,s)),memset(b,x=0,H*H);x'\ +'e?(*& c_*r=5,r+e-r +_:2-19<-+?|(d==d),!n ?*d| *( (char**)+V+), ('\ +' +0,*d-7 ) -r+8)c:7:+++7+! r: and%9- 85! ()-(r+o):(+w,_+ A*(=er'\ +'i+(o)+b)),!write,(=_((-b+*h)(1,A+b,!!((((-+, a >T^l,( o-95=+))w?'\ +'++ &&r:b<<2+a +w) ((!main(n*n,V) , +-) ),l)),w= +T-->o +o+;{ &!'\ +'a;}return _+= ' < herrmann2.ioccc +``` + +Note that with this it generates the original source code _prior to the clang +fix_! This is a nice way to get the original prefixed version! + +This also works with 32-bit: + +```sh +./herrmann2 "234 84 045 5 6765 7487 65190 84 656 254 12 43931 818 0 6542 \ +341 45 567 76967 7244 606 976567 895 81898 095 68678 1843 4650547 \ +565980691 389 04974" < herrmann2.ioccc +``` + +On the other hand these work with 64 bit (`Mach` or `x86_64`): + +```sh +./herrmann2 < herrmann2.ioccc +./herrmann2 < herrmann2.cup +``` + +A few notes from Cody: + +- The author stated that there are some layout restrictions and the changes made +to get it to compile with clang might have impacted this some. However given +that it appears to function correctly as long as it is compiled as a 32-bit +binary both before and after the fix this is probably not relevant. +- The author said that to add a function call one has to 'fill an entire line +with stuff doing mostly nothing' but it was not specified what an entire line is +nor what will happen otherwise. This is seen throughout the code and is likely +the source of dead code and variable declarations being repeated. +- At one point (not originally) my fix involved calling another function this +was done to try and find more about the crash. However this caused the program +to crash with the invocations that work as long as it's compiled with 32-bit so +this has been rolled back. This might be due to the restrictions noted in this +item and the above one but I'm not sure. +- The entry will give different output each invocation! But what you'll see is that +each line has a repeating pattern! This is expected. See below for an example +few lines. +- There are some multiple and unsequenced modifications to some variables. See +below for these. This again does not seem to matter in 32-bit - at least +theoretically. +- See below for possible crash locations when compiled as 64-bit. + + +The remaining unsequenced modification warnings are: + +``` +herrmann2.c:6:12: warning: multiple unsequenced modifications to 'n' [-Wunsequenced] +(0,&e,o||n -- +(0,&e,o||n -- +(0,&o||n ,o-- +(0,&on ,o-4,- +(0,n ,o-=94,- +(0,n + ^ ~~ +herrmann2.c:6:42: warning: unsequenced modification and access to 'o' [-Wunsequenced] +(0,&e,o||n -- +(0,&e,o||n -- +(0,&o||n ,o-- +(0,&on ,o-4,- +(0,n ,o-=94,- +(0,n + ^ ~ +herrmann2.c:11:65: warning: unsequenced modification and access to 'r' [-Wunsequenced] +5,r+e-r +_:2-195,r+e-r +_:2-195+e-r +_:2-1<-95+e-r +_-1<-95+e-r ++?_-1<-95+e-r + ~ ^ +herrmann2.c:18:68: warning: unsequenced modification and access to 'b' [-Wunsequenced] +-b+*h)(1,A+b,!!-b+*h),A+b,((!!-b+*h),A+b,!!-b+((*h),A+b,!!-b+*h),A-++b,!!-b+*h) + ^ +``` + +``` +6ejZR}DU}*u?CI)6ejZR}DU}*u?CI)6ejZR}DU}*u?CI)6ejZR}DU}*u?CI)6ejZR}DU}*u?CI)6ejZ +``` + +If you break it up you get: + +``` +6ejZR}DU}*u?CI) +6ejZR}DU}*u?CI) +6ejZR}DU}*u?CI) +6ejZR}DU}*u?CI) +6ejZR}DU}*u?CI) +6ejZ +``` + +which you can see is quite similar. + +As for crash locations: + +``` +Program terminated with signal SIGSEGV, Segmentation fault. +#0 main (n@entry=, V@entry=) at herrmann2.c:22 +22 )+0, +[...] +``` + +Note that that's not a `+` and the letter O; it's a zero! + +Since I broke the line down here's what the line looks like correctly: + +```c ++0,*d-7 ) -r+8)+0,*d-7 -r+8)+0,*d-c:7 -r+80,*d-c:7 -r+7:80,*d-7 -r+7:80,*d++-7 +``` + +What happens if we remove the `+0`? We then get on line 13: + +``` +*( (char**)+(int)V+ *( (char)+(int)V+ *( (c),har)+V+ (c),har)+ (V+ (c),r)+ (V+ ( c), + +``` + +Breaking this line down and we see it's still line 13: + +``` +13 * +14 ( (char**)+ +15 (int)V+ +16 *( (char)+ +17 (int)V+ +``` + +So let's merge the lines a bit: + +``` +#0 main (n@entry=, V@entry=) at herrmann2.c:13 +13 *( (char**)+(int)V+ +(gdb) bt +#0 main (n@entry=, V@entry=) at herrmann2.c:13 +(gdb) p (char**)+(int)V +$1 = (char **) 0xffffffff831602d8 +(gdb) p *(char**)+(int)V +Cannot access memory at address 0xffffffff831602d8 +``` + +Still line 13. Let's do it again: + +``` +#0 0x0000000000401442 in main (n@entry=, V@entry=) at herrmann2.c:13 +13 *( (char**)+(int)V+ *( (char)+ (int)V+ *( (c), har)+ V+ (c), har)+ (V+ (c), r)+ (V+ ( c), + 0, *d - 7 ) -r +8), +(gdb) p *(( (char**)+(int)V+ *( (char)+ (int)V+ *( (c), har)+ V+ (c), har)+ (V+ (c), r)+ (V+ ( c), + 0, *d - 7 ) -r +8)) +Cannot access memory at address 0xffffffffbfa05960 +(gdb) p *( ( char**)+(int)V) +Cannot access memory at address 0xffffffffbfa05958 +(gdb) p *( ( char**)+(int)V)+*((char)+(int)V) +Cannot access memory at address 0x58 +(gdb) p *( (char)+ (int)V ) +Cannot access memory at address 0x58 +(gdb) p (int)V+*((c),har) +$1 = -1080010408 +(gdb) ptype (int)V+*((c),har) +type = int +(gdb) p V +$2 = (char **) 0x7fffbfa05958 +(gdb) p (int)V +$3 = -1080010408 +(gdb) ptype V +type = char ** +(gdb) p *V +$4 = 0x7fffbfa07323 "./herrmann2" +(gdb) ptype (int)V +type = int +(gdb) q + +``` + +and so on. Note that with the fix for clang `V` is a `char **` not an int hence +the casts. But is this relevant? Let's find out: + +``` +#0 0x0000000000401440 in main (n@entry=, V@entry=) at herrmann2.c:14 +14 +0,*d-7 ) -r+8)+0,*d-7 -r+8)+0,*d-c:7 -r+80,*d-c:7 -r+7:80,*d-7 -r+7:80,*d++-7 +``` + +Now it's a different line! Can we fix this? + +``` +#0 main (n@entry=, V@entry=) at herrmann2.c:21 +21 +0, +``` + +Again `+0`! Let's remove it: + +``` +#0 main (n@entry=, V@entry=) at herrmann2.c:13 +13 *( (char**)+V+ *( (char)+V+ *( (c),har)+V+ (c),har)+ (V+ (c),r)+ (V+ ( c), +(gdb) p *( (char **)V) +Cannot access memory at address 0x544777d8 +``` + +So now it's back to the same problem which means that it's most likely not +because of the fix for clang. Still if you have a 32-bit compiler/linker you can +run the program; else you can at least run the alt version that works in part. + +Do you have a fix for 64-bit compilation? Please provide it! +## [2001/kev](2001/kev/kev.c) ([README.md](2001/kev/README.md) +## STATUS: INABIAF - please **DO NOT** fix + +Sometimes when one player presses `q` it will result in broken pipe on the other +end. + +The author also noted that some versions of `curses` have problems with +`getch()` having a delay. + +The program is very likely to segfault if the specified port can't be bound or +connected to. + +If the terminal is too wide (the author suggests over 500 characters) the +program can segfault. + +It's also possible to crash the program if a player scores over a billion +points. + +Although it is independent of endianness both systems need the same character +set. In other words both have to be ASCII or EBCDIC - not one of each. + +## [2001/ollinger](2001/ollinger/ollinger.c) ([README.md)(2001/ollinger/README.md)) +## STATUS: INABIAF - please **DO NOT** fix + +This program will very likely crash or do something else without an arg. + + + +## [2001/schweikh](2001/schweikh/schweikh.c) ([README.md](2001/schweikh/README.md)) +## STATUS: INABIAF - please **DO NOT** fix + +This program will very likely crash or do something else if you do not give it +two args. + +Note also that the glob pattern must match the whole string. See the author's +comments for details and a workaround. + +There's also no way to escape meta characters. + +# 2002 + +There was no IOCCC in 2002. + +# 2003 + +There was no IOCCC in 2003. + +# 2004 + + +## [2004/burley](2004/burley/burley.c) ([README.md](2004/burley/README.md)) +## STATUS: known bug - please help us fix + +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed this to compile +with clang. He notes however that both prior to the fix (with gcc) and after the +fix (gcc, clang) it does not work: it allows input of the bet but after it +prints the hand it does not do anything with your next move. Cody provided the +following notes and tips (including possible reasons it doesn't work): + +0. Originally the `jmp_buf` was just an `int p[4][1000]`. +1. The `setjmp.h` header file was not included so the calls to `longjmp()` had +not only the wrong number of arguments but also implicitly returned int when it +actually returns void. This means that the comma operator had to be used to get +the binary expressions to work. It might be this is part of the problem. It's +possible that actually changing this introduced it to not work as some old +entries actually use invalid prototypes and work but changing them to use the +proper prototype breaks them. +2. Another possible problem is the abuse of `setjmp()` and `longjmp()` which is +known to be a problem, at least as he interprets it in his tired head (and less +experience with `longjmp`). In particular: + > The longjmp() routines may not be called after the routine which called the + > setjmp() routines returns. + See also the NOTES section of the linux man pages for `setjmp(3)` and + `longjmp(3)`. +3. The main() originally returned a call to main() which appeared to be an +infinite recursion at least as it was; now it returns a call to poke() (since +it's a poker game) which has the same number and type of args (1, `char *`) that +main() originally had. This appears to not be an infinite recursion but I might +be reading it wrong. Changing it to not return itself and the same problem +occurs so perhaps this is not the problem. It's possible that the initial call +to the `poke()` function is incorrect. +4. It might be that the requirement of the comma operator in modern compilers is +a problem. Perhaps some instances of `,1` should be `,0`? That seems plausible +as they are often used with the `&&` operator. +5. As well main() had only one arg, a `char *`, and there was a (seemingly) +needless cast to `char *` from gets(). This cast remains in the code however. +6. The code no longer uses `gets()` but `fgets()`; this is not the problem +however. +7. Sometimes the lack of a _proper_ prototype lets code work if the function is +used incorrectly so one should be careful with adding the proper prototypes. +With this entry it didn't _appear_ to be relevant but maybe it is after another +change? + # 1997 There was no IOCCC in 1997. @@ -795,58 +1547,38 @@ fix this (in fact it was originally done but rolled back). # 2001 -## [2001/anonymous](2001/anonymous/anonymous.c) ([README.md](2001/anonymous/README.md)) -## STATUS: known bug - please help us fix - -This entry seems to no longer work and we would appreciate any help from anyone -who can fix this. [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) has -the following hints that might help but he has no system where he could test -it. [Yusuke Endoh](/winners.html#Yusuke_Endoh) [wrote a little bit about -it](https://mame-github-io.translate.goog/ioccc-ja-spoilers/2001/anonymous.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=en-US&_x_tr_pto=wapp) that -might or might not help but he too could not get it to work. - -Tips from Cody: - -- Try a beautifier on the original C code. -- Use cpp to make the functions easier to parse. For instance if you're in the -directory try `cpp -E anonymous.cp > anonymous.cpp` and look at that file to see -the functions. It might or might not be helpful to use cpp on the beautified -source. -- After beautifying it try changing references of the macros (where not too -complicated) to their definitions. For instance in vim you might do: -`:%s/\/int */g` and then delete the line that was changed to `#define int * -int*` (or else do a range substitute so it's not changed). You might not need -this if you use the cpp. This might be useful anyway to more easily test things. -- If your system has a `setarch` tool that might or might not be of help (I'm -not too familiar with its internals). -- The code appears to do everything from one call to `exit(3)` but it makes use -of the ternary operator and possibly the comma operator. -- Check the Makefile for the defines but also observe that those are in the -source file. It appears that the entry might try compiling as well but that's -from a quick glance. -- The original main() started like: `main (char *ck, char **k)` but we made it -compilable for clang by changing it to be: `main (int cka, char **k) { char *ck -= (char *)cka;` which might or might not be good. -- The author warns that only simple source (once compiled) would work so make -use of the provided source file -[2001/anonymous/anonymous.ten.c](2001/anonymous/anonymous.ten.c). To compile try -`make anonymous.ten` from the entry directory which you can then run the entry -on. Note that it needs to be compiled as a x86 program. -- The program will to an extent destroy files it is used on. See the author's -warning in their comments on that. - - ## [2001/bellard](2001/bellard/bellard.c) ([README.md](2001/bellard/README.md)) -## STATUS: possible bug (possibly depending on system) - please help test and if necessary fix +## STATUS: probable bug (possibly depending on system) - please help test and if necessary fix [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed an initial segfault and he also fixed the [supplementary -program](2001/bellard/bellard.otccex.c) to test the entry on to not segfault and -seemingly work but he has no 32-bit system to test any further fixes and we +program bellard.otccex.c](2001/bellard/bellard.otccex.c) to test the entry on to not segfault and +seemingly work but he has no 32-bit system to test any further fixes; we would greatly appreciate anyone's help! It appears that this entry will require major debugging and to make it work one might need to have a deep understanding of the ELF format. +The author said that they compiled it with [gcc version +2.95.2](https://ftp.gnu.org/gnu/gcc/gcc-2.95.2/gcc-everything-2.95.2.tar.gz). We don't know if +a certain gcc version is necessary but it might be helpful to download and +compile that version to test it. + +## [2001/westley](2001/westley/westley.c) ([README.md](2001/westley/README.md)) +## STATUS: missing files - please provide them + +The author referred to the file `card.gif` but this appears to be missing. Do +you have it? If you do please provide it and thank you! + +## STATUS: uses gets() - change to fgets() if possible (in some cases getline() works) + +The code also uses `gets()` which, without redirecting stderr to `/dev/null`, +can show an obnoxious warning every time it's run. In the script +[2001/westley/westley.sh](2001/westley/westley.sh) that [Cody Boone +Ferguson](/winners.html#Cody_Boone_Ferguson) added stderr is in fact redirected +to `/dev/null` to prevent this warning but it would probably be better if it was +changed to use `fgets()` (which he might end up doing). + + # 2002 There was no IOCCC in 2002. @@ -896,6 +1628,10 @@ as they are often used with the `&&` operator. needless cast to `char *` from gets(). This cast remains in the code however. 6. The code no longer uses `gets()` but `fgets()`; this is not the problem however. +7. Sometimes the lack of a _proper_ prototype lets code work if the function is +used incorrectly so one should be careful with adding the proper prototypes. +With this entry it didn't _appear_ to be relevant but maybe it is after another +change? ## [2004/gavin](2004/gavin/gavin.c) ([README.md](2004/gavin//README.md)) @@ -1000,39 +1736,138 @@ gavin_files: boot.b lilo.conf prim gavin_install.txt The current ([Makefile](2004/gavin/Makefile) was modified to try and fit into the current IOCCC build environment. +## [2004/sds](2004/sds/sds.c) ([README.md](2004/sds/README.md)) +## STATUS: INABIAF - please **DO NOT** fix + +The generated code will very likely segfault or do something not intended if not +given the right args. See the README.md file for the correct syntax. + # 2005 +## [2005/anon](2005/anon/anon.c) ([README.md](2005/anon/README.md)) +## STATUS: INABIAF - please **DO NOT** fix + +This program sometimes will create unsolvable puzzles :-) just to hook you. +As a protection against this - and to prevent you from spending too much time on +such puzzles (or too big puzzles if you insist on doing this) - it deliberately +destroys its runtime stack. See the [README.md](2005/anon/README.md) for more +details on this. + +If you specify more than three args the program might also crash or do something +strange. This might also happen if you specify excessively large board +dimensions. Try `100 100 100` for instance and see what happens! + ## [2005/giljade](2005/giljade/giljade.c) ([README.md](2005/giljade/README.md)) -## STATUS: doesn't work with some platforms - please help us fix +## STATUS: known bug - please help us fix -[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) noted that this -requires both 32-bit CPUs (data size?) and also cannot have the optimiser -enabled. It might be that it can be fixed, perhaps by changing the int sizes -and bitwise operations, but if not this will not work with some systems like -modern Macs as Apple has made it quite difficult to compile 32-bit applications -(thanks a lot Apple for ruining some IOCCC entries! :-) ). +Landon Curt Noll fixed this entry to work with clang by changing the first arg +to be an `int` and the second arg to be a `char **`. This is important because +of clang's deficiency requiring args to be one type only. -It's quite probable that non x86 related CPUs will also not work: it's hard to -know because Cody's only non-x86 (x86_64 in particular) system is the MacBook -Pro Max with the M1 chip which is arm64 and unfortunately specifying `-m32` is -invalid on that system (might be on Intel 64-bit Macs as well but he hasn't had -one since before November 2022). +This did not completely fix the problem for the program however. +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) observed that it has to +be compiled with `-m32` which is not possible in modern macOS. It also cannot +have the compiler optimiser enabled. Cody fixed it so that it works in 64-bit +but the clang fix does break something in the entry, specifically that the +self-test feature of the program no longer works. + +One is supposed to be able to do: + +```sh +./giljade > out +./giljade out +``` + +and see all layouts compile without error. If you wish to see this in action and +you have a compiler without the deficiency of clang you can do: + +```sh +make alt +./giljade.alt > out +./giljade out + +``` + +(You don't need to use `giljade.alt` to test compile - it's the output of the +program that's the actual problem.) + +But the issue is can it be fixed for clang. If you have a fix we welcome your +help! Believe it or not this appears in part to be due to more than two spaces in +the program except in the places where the original code has them. This however +does not seem to be the full story. Cody probably will look at this again but +for now we note this problem here. + +## STATUS: INABIAF - please **DO NOT** fix + +It also will very likely segfault or do something strange if the source code +does not exist. ## [2005/mynx](2005/mynx/mynx.c) ([README.md](2005/mynx/README.md)) ## STATUS: INABIAF - please **DO NOT** fix [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) notes that, though -probably obvious, this entry will not work with https. He changed the code to -scan for https too (it exited before) in case someone comes up with a clever -command line to make it work but the problem is a secure connection has to first -be set up in order to give http commands. This is not a bug but it's worth -pointing out as it won't work on as many websites as it used to including the -[IOCCC website](https://www.ioccc.org) itself. +probably obvious, this entry will not work with https. He added an alt version +that scans for https in case someone wants to set up a pipeline or other +workaround (perhaps with stunnel) but the problem otherwise is a secure +connection has to first be set up in order to give http commands. This is not a +bug but it's worth pointing out as it won't work on as many websites as it used +to including the [IOCCC website](https://www.ioccc.org) itself. # 2006 + +## [2006/hamre](2006/hamre/hamre.c) ([README.md](2006/hamre/README.md)) +## STATUS: INABIAF - please **DO NOT** fix + +This program will very likely crash or do something completely irrational :-) if +you don't supply it with an argument. + +As well supplying more arguments will possibly limit the number of nested +operators supported. + +Don't try dividing by 0 (zero). + +## [2006/monge](2006/monge/monge.c) ([README.md](2006/monge/README.md)) +## STATUS: INABIAF - please **DO NOT** fix + +Incorrect formulas will ungracefully crash the program. + +## [2006/stewart](2006/stewart/stewart.c) ([README.md](2006/stewart/README.md)) +## STATUS: INABIAF - please **DO NOT** fix + +This program will very likely crash or do something funny if the file does not +exist or cannot be opened. + +## [2006/toledo2](2006/toledo2/toledo2.c) ([README.md](2006/toledo2/README.md)) +## STATUS: INABIAF - please **DO NOT** fix + +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed this program to +not crash in macOS (it appeared to work fine in fedora linux on an `x86_64` +architecture but he does not know if it crashed in macOS Ventura due to the fact +it is an `arm64` CPU - the Apple silicon chip). This fix, BTW, is a mix of a fix +by [Yusuke Endoh](/winners.html#Yusuke_Endoh) and Cody's. Nevertheless there are +two features that are not bugs and one bug (see below). + +By design this program is supposed to crash on termination. + +You must type in caps (except in strings) and this program is indeed +case-sensitive. + +## STATUS: known bug - please help us fix + +The author showed something like this in their remarks: + +```sh +./toledo2 DDT.COM +A> IMPORT DDT.COM +``` + +but the `A>` prompt never appears; instead it's just the same as if you +specified no arg. + + # 2007 # 2008 # 2009 @@ -1043,6 +1878,112 @@ These years did not have an IOCCC. # 2011 +## [2011/dlowe](2011/dlowe/dlowe.c) ([README.md](2011/dlowe/README.md)) +## STATUS: missing or dead link - please provide them + +The author's website, http://www.pootpoot.net, no longer exists as it once did, +instead being something else entirely. The Internet Wayback Machine, although it +archived it, did not load scripts. Do you know if the domain was moved? Do you +have an archive or mirror? Please provide us it! Thank you. + +## STATUS: INABIAF - please **DO NOT** fix + +The author states the following: + +* Bad input (e.g. nonexistent files, non-numeric number of iterations, etc.) +tends to result in empty output. + +* Given exactly one corpus, the program will crash or produce garbage. + +* Leaks memory and file descriptors while processing files. + +* Will crash and die horribly if it runs out of memory. + + +## [2011/richards](2011/richards/richards.c) ([README.md](2011/richards/README.md)) +## STATUS: doesn't work with some platforms - please help us fix + +This does not appear to work with macOS, resulting in a segfault. We're not +sure if this is to do with the Apple silicon chip or not but it seems unlikely. +At first glance it appeared to be that it might be the function pointers. These +were changed a bit and it might have helped a bit but this is not certain +either. What was noticed is that there is an overflow according to `asan`: + + +``` +==32361==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x00016d368d08 at pc 0x000102b1dcb0 bp 0x00016d368b90 sp 0x00016d368b88 +READ of size 8 at 0x00016d368d08 thread T0 + #0 0x102b1dcac in rd richards.c:128 + #1 0x102b1e1f4 in re richards.c:145 + #2 0x102a7e7e0 in t richards.c:104 + #3 0x102b1f7cc in main richards.c:185 + #4 0x19498ff24 () + +Address 0x00016d368d08 is located in stack of thread T0 at offset 40 in frame + #0 0x102b1dae8 in rd richards.c:125 + + This frame has 1 object(s): + [32, 40) 'a' (line 126) <== Memory access at offset 40 overflows this variable +HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork + (longjmp and C++ exceptions *are* supported) +SUMMARY: AddressSanitizer: stack-buffer-overflow richards.c:128 in rd +Shadow bytes around the buggy address: + 0x00702da8d150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702da8d160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702da8d170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702da8d180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702da8d190: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 +=>0x00702da8d1a0: 00[f3]f3 f3 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702da8d1b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702da8d1c0: f1 f1 f1 f1 00 f3 f3 f3 00 00 00 00 00 00 00 00 + 0x00702da8d1d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702da8d1e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702da8d1f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +Shadow byte legend (one shadow byte represents 8 application bytes): + Addressable: 00 + Partially addressable: 01 02 03 04 05 06 07 + Heap left redzone: fa + Freed heap region: fd + Stack left redzone: f1 + Stack mid redzone: f2 + Stack right redzone: f3 + Stack after return: f5 + Stack use after scope: f8 + Global redzone: f9 + Global init order: f6 + Poisoned by user: f7 + Container overflow: fc + Array cookie: ac + Intra object redzone: bb + ASan internal: fe + Left alloca redzone: ca + Right alloca redzone: cb +==32361==ABORTING + +``` + +This was reported in both linux as 32-bit and 64-bit and macOS as 64-bit except +that the sizes were different in 32-bit (as expected). The code it is having a +problem with is: + +```c + o *a = 0, **b = &a, **c = b + 24; + x[v] = w; + for (; b < c && (*b < (o *)w || *b > (o *) T || *b == (long) v); b++); + +``` + +where `o` is a `void`. + +Do you have a fix? We welcome it! + +## [2011/vik](2012/vik/vik.c) ([README.md](2012/vik/README.md)) +## STATUS: INABIAF - please **DO NOT** fix + +The author stated that the program will crash if no argument is passed tot he +program though we note that your computer might also [halt and catch +fire](https://en.wikipedia.org/wiki/Halt_and_Catch_Fire_(computing)) :-) + # 2012 diff --git a/faq.md b/faq.md index e8dcf2ce8..c7dd9974d 100644 --- a/faq.md +++ b/faq.md @@ -172,6 +172,13 @@ fix. If it is accepted we'll be happy to credit you in the entry's _README.md_ file. If you're a previous winner we will happily link to your entries; if you're not we can link to your website if you wish. +## Q: After running a program my terminal is all messed up! How do I restore my terminal? + +The simplest way to do this is to type `reset`. If echo was disabled you can get +away with `stty echo`. Sometimes you can also get away with `stty sane`. `reset` +does the most but note that it will clear the screen (`clear` will too but it +won't reset the terminal). + ## Q: Are there types of entries that are submitted so frequently that the judges get tired of them? Yes, there are types of entries that show up over and over again. @@ -283,7 +290,7 @@ _**...it's so 20th century...**_ HINT: It is not fatal to send in those types of entries, it is just MUCH HARDER to win. Such an entry would have to do something _really unique **AND** interesting_ to even make it into the final judging rounds. Entries that -re-use these 'worn out' themes frequently lose to other entries that do +reuse these 'worn out' themes frequently lose to other entries that do something different. HINT: If you really MUST send in an entry based on an 'overused theme', be sure @@ -395,7 +402,7 @@ We are not accepting mirror requests at this time, sorry. ## Q: I want to publish some parts of the IOCCC in an article, or book, or newsletter, or use then in class/instructional notes, or quote from the IOCCC. May I do so? -Please ask the IOCCC judges first. Please send your request using the +Please ask the [IOCCC judges](/judges.html) first. Please send your request using the instructions on the [contacting the IOCCC Judges](/contact.html) page. ## Q: What are the grand prize / Best of Show winners? diff --git a/tmp/README.md b/tmp/README.md index b11f159c6..ce9e0f913 100644 --- a/tmp/README.md +++ b/tmp/README.md @@ -6,5 +6,14 @@ For example: CVS text files, that will later be used to generate JSON files. The files currently available (as of 08 April 2023, added 07 April): +On 07 April 2023 the following files were added: + - [year-auth-prize.csv](year-auth-prize.csv) - list of winning entries by author, year and prize - [winners.csv](winners.csv) - list of winning authors + +On 12 April 2023 the following files were added: + +- [example.author_handle.json](example.author_handle.json) - fictitious author +for individual author json files +- [example.dot_winner.json](example.dot_winner.json) - fictitious winning entry +json file diff --git a/tmp/winners.csv b/tmp/winners.csv index c37133f89..d8d21919d 100644 --- a/tmp/winners.csv +++ b/tmp/winners.csv @@ -1,198 +1,197 @@ -# name,winner_handle,url,email,country,mastodon/twitter -Anonymous,Anonymous_1984,null,null,null,null,null); -Anonymous,Anonymous_2004,http://bicoherent.topcities.com/,null,null,null,null); -Anonymous,Anonymous_2005,null,null,null,null,null); -bsoup,bsoup,null,,mail@bsoup.skr.jp,null,null); -Aaron Grothe,Aaron_Grothe,null,null,ajgrothe@yahoo.com,US,null); -Adar Zeitak,Adar_Zeitak,null,null,aa4z2@walla.co.il,null,null); -Adrian Cable,Adrian_Cable,null,null,null,null,null); -Adrian Mariano,Adrian_Mariano,http://cam.cornell.edu/adrian/,null,adrian@cam.cornell.edu,null,null); -Aidan Thornton,Aidan_Thornton,null,null,makomk@lycos.co.uk,United Kingdom,null); -Alan De Smet,Alan_De_Smet,http://www.upl.cs.wisc.edu/~chaos/,null,chaos@null.net,null,null); -Albert van der Horst,Albert_van_der_Horst,http://home.hccnet.nl/a.w.m.van.der.horst,null,albert@spenarnc.xs4all.nl,null,null); -Alex Deckmyn,Alex_Deckmyn,null,null,alex.deckmyn@gmail.com,null,null); -Alexander Prishchepov,Alexander_Prishchepov,https://github.com/sans17/,null,student.00x@gmail.com,null,null); -Anders Gavare,Anders_Gavare,http://www.mdstud.chalmers.se/~md1gavan/,null,md1gavan@mdstud.chalmers.se,null,null); -Andrea Marangoni,Andrea_Marangoni,http://www.andreamarangoni.it,null,andrea@andreamarangoni.it,null,null); -Andreas Gustafsson,Andreas_Gustafsson,http://www.araneus.fi/gson/,null,gson@araneus.fi,null,null); -Andrew T. Shapiro,Andrew_Shapiro,null,null,null,null,null); -Andy Sloane,Andy_Sloane,null,null,null,US,null); -Anthony C. Howe,Anthony_C._Howe,http://www.snert.com/,null,achowe@snert.com,Montreal, Quebec -Anton Älgmyr,Anton_Älgmyr,null,null,algmyr@student.chalmers.se,null,@aalgmyr); -Arch D. Robison,Arch_D_Robison,null,null,null,null,null); -Arne "Timwi" Heizmann,Arne_"Timwi"_Heizmann,null,null,timwi@gmx.net,Germany,null); -Baruch Nissenbaum,Baruch_Nissenbaum,null,null,baruch@eng.tau.ac.il,null,null); -Bas de Bakker,Bas_de_Bakker,null,null,bas@bbwt.demon.nl,null,null); -Ben Lynn,Ben_Lynn,https://crypto.stanford.edu/~blynn/,null,benlynn@gmail.com,null,@bmxlynn); -Bernd Meyer,Bernd_Meyer,http://byron.csse.monash.edu.au/,null,bmeyer@cs.monash.edu.au,null,null); -Brent Burley,Brent_Burley,null,null,brent.burley@disney.com,null,null); -Brian Westley,Brian_Westley,http://www.westley.org,null,brian@westley.org,null,null); -Bruce Holloway,Bruce_Holloway,null,null,null,null,null); -Byron Rakitzis,Byron_Rakitzis,null,null,null,null,null); -Carl Banks,Carl_Banks,http://www.personal.psu.edu/users/c/w/cwb129/,null,cwb129@alumni.psu.edu,null,null); -Carl Shapiro,Carl_Shapiro,null,null,carl@lasvegassun.com,null,null); -Carlos Duarte,Carlos_Duarte,null,null,null,null,null); -Cel Skeggs,Cel_Skeggs,http://www.celskeggs.com,null,celskeggs@gmail.com,null,null); -Chris King,Chris_King,null,null,ctk314@yahoo.com,null,null); -Christian Dupont,Christian_Dupont,null,null,christian.dupont@lemel.fr,null,null); -Christopher Mills,Christopher_Mills,null,null,mrxo@sonic.net,null,@MisterXopher); -Christopher Night,Christopher_Night,http://www.people.fas.harvard.edu/~night/,null,null,US,null); -Cody Boone Ferguson,Cody_Boone_Ferguson,https://ioccc.xexyl.net,null,ioccc@xexyl.net,US,https://fosstodon.org/@xexyl); -Col. G. L. Sicherman,Col._G._L._Sicherman,http://www.monmouth.com/~colonel/,null,colonel@monmouth.com,null,null); -Craig Schneiderwent,Craig_Schneiderwent,null,null,evilgenius@attglobal.net,null,null); -Daniel Fischer,Daniel_Fischer,null,null,df@freudenstadt.net,null,null); -Daniel J. Bernstein,Daniel_J._Bernstein,http://pobox.com/~djb/djb.html,null,djb@pobox.com,null,null); -Daniel Vik,Daniel_Vik,http://danielvik.com/,null,null,null,null); -Dave Burton,Dave_Burton,http://snox.net/ioccc,null,daveb@snox.net,US,@lv2jmp); -Dave Decot,Dave_Decot,null,null,null,null,null); -David Applegate,David_Applegate,http://www.caam.rice.edu/~davida,null,davida@caam.rice.edu,null,null); -David Gibson,David_Gibson,null,null,null,null,null); -David Goodenough,David_Goodenough,null,null,null,null,null); -David Korn,David_Korn,http://www.kornshell.com/~dgk/,null,dgk@research.att.com,null,null); -David Lowe,David Lowe,http://pootpoot.com/,null,david@pootpoot.com,null,null); -David Madore,David_Madore,http://www.madore.org/~david/,null,david+alexander@madore.org,null,null); -David Van Brackle,David_Van_Brackle,http://east.isx.com/~vanb/,null,vanb@east.isx.com,null,null); -Dean Swift,Dean_Swift,http://www.tc3.co.uk/~gandalf/G.HTML,null,null,null,null); -Derek Anderson,Derek_Anderson,null,null,dereka9991@gmail.com,null,null); -Diomidis Spinellis,Diomidis_Spinellis,http://www.spinellis.gr,null,dds@aueb.gr,null,null); -Dominik Muth,Dominik_Muth,null,null,dominik.muth@gmx.de,null,null); -Don Dodson,Don_Dodson,http://www.neta.com/~dodson/,null,null,null,null); -Don Yang,Don_Yang,http://uguu.org/,null,omoikane@uguu.org,null,null); -Doron Osovlanski,Doron_Osovlanski,http://www.cadtech.co.il/profile.html,null,null,null,null); -Doug Beardsley,Doug_Beardsley,null,null,dgbeards@southern.edu,null,null); -E. Jay Berkenbilt,E._Jay_Berkenbilt,null,null,null,null,null); -Ed Luke,Ed_Luke,http://www.erc.msstate.edu/~lush,null,lush@erc.msstate.edu,null,null); -Ed Lycklama,Ed_Lycklama,http://www.klg.com,null,eal@klg.com,null,null); -Edward Giles,Edward_Giles,https://id523a.com/,null,edward@giles.net.au,null,null); -Edward Rosten,Edward_Rosten,http://users.ox.ac.uk/~scat1148,null,scat1148@herald.ox.ac.uk,null,null); -Eric Marshall,Eric_Marshall,null,null,eric@EMIEng.com,null,null); -Eryk Kopczynski,Eryk_Kopczynski,http://www.mimuw.edu.pl/~erykk/,null,ek189185@zodiac.mimuw.edu.pl,null,null); -Esko Nuutila,Esko_Nuutila,http://www.cs.hut.fi/~enu/,null,enu@cs.hut.fi,null,null); -Etienne Duble,Etienne_Duble,https://lig-membres.imag.fr/duble,null,etienne.duble@gmail.com,null,@etienne_duble); -Fabrice Bellard,Fabrice_Bellard,https://bellard.org/,null,fabrice@bellard.org,null,null); -Ferenc Deak,Ferenc_Deak,null,null,null,null,null); -Francois Boutines,Francois_Boutines,null,null,francois.boutines@gmail.com,Toulouse, France -Frans van Dorsselaer,Frans van Dorsselaer,null,null,frans@biabv.com,null,null); -Freek Wiedijk,Freek_Wiedijk,null,null,null,null,null); -Garry Glendown,Garry_Glendown,https://web.archive.org/web/20011221120305/http://insider.regio.net/~garry/,null,garry@insider.regio.net,null,null); -Gavin Barraclough,Gavin_Barraclough,null,null,gavin@barraclough.name,null,null); -Gavin Buttimore,Gavin_Buttimore,null,null,gavin.buttimore@creaturelabs.com,null,null); -Gil Dogon,Gil_Dogon,null,null,gil.jade@gmail.com,null,null); -Glyn Anderson,Glyn_Anderson,null,null,glyn@mataharistudios.com,null,null); -Gopi Reddy,Gopi_Reddy,null,null,null,null,null); -Gregor Richards,Gregor_Richards,null,,Richards@codu.org,null,null); -Heather Downs,Heather_Downs,http://www.bungalow.com/,null,heather@bungalow.com,null,null); -Ian Collier,Ian_Collier,http://www.comlab.ox.ac.uk/oucl/users/ian.collier/,null,imc@comlab.ox.ac.uk,UK,null); -Ian Phillipps,Ian_Phillipps,null,null,ian@dial.pipex.com,null,null); -Ilya Kurdyukov,Ilya_Kurdyukov,https://github.com/ilyakurdyukov,null,olme8@mail.ru,null,@ilyakurdyukov); -Immanuel Herrmann,Immanuel_Herrmann,http://pcpool.mathematik.uni-freiburg.de/~immi/,null,immi@pcpool.mathematik.uni-freiburg.de,null,null); -J. David Lowe,J_David_Lowe,http://www.pootpoot.net/,null,j.david.lowe@gmail.com,US,null); -Jack Applin,Jack_Applin,http://www.geocities.com/HotSprings/6789/,null,neutron@fc.hp.com,null,null); -James A. Woods,James_A._Woods,null,null,null,null,null); -James Bonfield,James_Bonfield,null,null,jkb@mrc-lmb.cam.ac.uk,null,null); -Jan Stein,Jan_Stein,null,null,null,null,null); -Jari Arkko,Jari_Arkko,http://www.arkko.com,null,jari@arkko.com,null,null); -Jason Orendorff,Jason_Orendorff,http://www.jorendorff.com/,null,jason@jorendorff.com,null,null); -Jay Vosburgh,Jay_Vosburgh,null,null,fubar@sequent.com,null,null); -Jeff Newbern,Jeff_Newbern,null,null,jnewbern@yahoo.com,null,null); -Jeff Weisberg,Jeff_Weisberg,http://www.op.net/~jaw,null,jaw@op.net,null,null); -Jens Schweikhardt,Jens_Schweikhardt,http://www.schweikhardt.net,null,schweikh@schweikhardt.net,null,null); -Jetro Lauha,Jetro_Lauha,http://jet.ro,null,null,FI,null); -Jim Hague,Jim_Hague,http://www.oxinet.co.uk/jim,null,bears@cix.compulink.co.uk,null,null); -John Dalbec,John_Dalbec,http://cc.ysu.edu/~jpdalbec/,null,jdalbec@cboss.com,null,null); -John Tromp,John_Tromp,http://tromp.github.io/,null,john.tromp@gmail.com,null,null); -John Williams,John_Williams,null,null,williams@morinda.com,null,null); -Jon Thingvold,Jon_Thingvold,http://www.uio.no/~jonth/,null,jon.thingvold@usit.uio.no,null,null); -Jonathan Hoyle,Jonathan_Hoyle,http://www.jonhoyle.com,null,jonhoyle@mac.com,null,null); -Joshua Karns,Joshua_Karns,null,null,jkarns275@gmail.com,null,@jkarnss); -Jyrki Holopainen,Jyrki_Holopainen,http://personal.eunet.fi/pp/halo/,null,jyrki.holopainen@paetronics.fi,null,null); -Karl F. Fox,Karl_F._Fox,null,null,karl@ascend.com,null,null); -Ken Huffman,Ken_Huffman,http://www.huffmancoding.com,null,huffmancoding@gmail.com,null,null); -Kevin Pulo,Kevin_Pulo,//www.kev.pulo.com.au/,null,kev@pulo.com.au,null,null); -Kimmo Fredriksson,Kimmo_Fredriksson,null,,kimmo.k.k.fredriksson@gmail.com,null,null); -Larry Jones,Larry_Jones,null,null,lawrence.jones@siemens.com,null,null); -Larry Wall,Larry_Wall,http://www.wall.org/~larry/,null,larry@wall.org,null,null); -Laurion Burchall,Laurion_Burchall,http://www.netspace.org/users/ldb,null,ldb@netspace.org,null,null); -Lennart Augustsson,Lennart_Augustsson,http://www.cs.chalmers.se/~augustss,null,augustss@cs.chalmers.se,null,null); -Leonid A. Broukhis,Leonid_A._Broukhis,http://www.mailcom.com/leob,null,leob@mailcom.com,null,null); -Lord Zarbon,Lord_Zarbon,null,null,null,null,null); -Maarten Litmaath,Maarten_Litmaath,null,null,litmaath@cern.ch,null,null); -Marcin Ciura,Marcin_Ciura,null,null,mciura@gmail.com,null,@mciura); -Mark Biggar,Mark_Biggar,null,null,mark@biggar.org,null,null); -Mark Isaak,Mark_Isaak,null,null,null,null,null); -Mark Plummer,Mark_Plummer,http://www.nrgnet.com/markus,null,markus@nrgnet.com,null,null); -Mark Schnitzius,Mark_Schnitzius,null,null,schnitzi@gmail.com,null,null); -Mary Ann (Mark) Horton,Mark_Horton"> 2011 (and two + entries in 2011, vik and zucker) and possibly some of the earlier years. I + ([Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson)) have spent too + much time when working on formatting the README.md files on finding problems + out (and in some cases fixing or trying but not yet succeeding to fix an + entry); if I did not do that I would be done with fixing the README.md files + (format wise and mostly typos too). Of course when working on finding bugs + it might necessitate updating the README.md file but that can be done at + that time. I might or might not end up following this idea but I probably + should so this needs to be noted. + - Resolve as many of the issues in [bugs.md](/bugs.md) with the exception of the -INABIAF ones. This is likely not possible but some certainly can be fixed. -- Check for typos in README.md files. +INABIAF ones. This is likely not possible for all (one in particular comes to +mind that abuses a bug in a now very old gcc version - this obviously cannot be +fixed) but many certainly can be (and have been) fixed. + +- Check for typos in README.md files. Most years have been done. I (Cody) need +to check the late 80s through mid 1990s plus the last two entries in 2011 and +the following years. At the same time the formatting is being fixed. + +- Go through all year README.md files that is 1984/README.md, 1985/README.md and +so on. As of *Sun 30 Apr 2023 13:45:52 UTC* the following years have been +finished: 1984, 1985, 1986, 2004, 2005. + - Verify which README.md files have not been checked for correct formatting and fix any issues. - * This includes author information: not only at first column but making sure that the lines end with spaces so that the rendered output does not end up on one line only. * [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) has done many and has some kind of record of what he's done but these can be added later by having a list of years to check. + * NOTE: as of 03 May 2023 years up through most of 2011 have been checked + except that a few year I am pretty sure I did not check typos (I'd say about + 1987 or 1988 through 1995 should be rechecked for typos). It's very likely + I won't keep this updated until it's finished but I wanted to note it now. + +- Remove addresses from older winning entries but (if known) keep country code + +add country code to winners.csv. As of half past 4 Pacific time on 22 April 2023 +only the years through 1986 are done. This should not take much time but I +(Cody) am bored with it for now and would rather do other more important things. +This will likely not be updated until after it's done (and when I remember to +remove it - I expect that when I go for it I'll do it in one sitting or maybe a +few sittings with a few brief breaks). diff --git a/var.mk b/var.mk index 6cc9083d7..6f3bc0229 100644 --- a/var.mk +++ b/var.mk @@ -12,6 +12,7 @@ AWK= awk BANNER= banner BASE64= base64 BASENAME= basename +BASH= bash BATCH= batch BC= bc BINHEX= binhex diff --git a/winners.html b/winners.html index bafe89e17..4457e8f28 100644 --- a/winners.html +++ b/winners.html @@ -85,7 +85,7 @@ Contest

  • Dishonorable mention (1984 anonymous)
    -
  • Anonymous -- http://bicoherent.topcities.com/ +
  • Anonymous -- https://web.archive.org/web/20040324155828/http://bicoherent.topcities.com/
    @@ -100,7 +100,7 @@ Contest
  • Best X11 Graphics (1991 davidguy)
    -
  • Jack Applin -- http://www.geocities.com/HotSprings/6789/ +
  • Jack Applin -- http://www.geocities.com/HotSprings/6789/
    -
  • Lennart Augustsson -- http://www.cs.chalmers.se/~augustss +
  • Lennart Augustsson -- https://web.archive.org/web/20090831055828/http://www.cs.chalmers.se/~augustss