diff --git a/1984/anonymous/README.md b/1984/anonymous/README.md index 22ccd5ad9..020009c80 100644 --- a/1984/anonymous/README.md +++ b/1984/anonymous/README.md @@ -16,11 +16,10 @@ make all ``` [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 -your assistance! +under macOS. The fix was to not use implicit `int`s in the `read()` function as +it once did. 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 your assistance! ## Judges' remarks: diff --git a/1984/anonymous/anonymous.c b/1984/anonymous/anonymous.c index 8deda1980..7f7e3aed8 100644 --- a/1984/anonymous/anonymous.c +++ b/1984/anonymous/anonymous.c @@ -1,2 +1,2 @@ -int read(int,void*,int);i;main(){for(;i["] +#include + +main(argc, argv) char **argv; +{ + register FILE *fp; + register short pos = 0, c, n; + register char *fmt; + if (argc != 2) { + fprintf (stderr, "Usage: %s file\n", argv[0]); + exit (1); + } + + if ((fp = fopen(argv[1], "r")) == NULL) { + fprintf(stderr, "%s: can't open %s\n", argv[0], argv[1]); + exit(2); + } + + fseek (fp, (long) sizeof (struct exec), 0); + printf("/* portable between VAX and PDP11 */\n\n"); + printf ("short main[] = {\n"); + for (;;) { + if (pos == 0) + printf("\t"); + + c=getc(fp) & 0377; + if (feof(fp)) break; + n = getc(fp) << 8|c; + + switch (rand() % 5) { + case 0: + case 1: + fmt = "%d"; break; + case 2: + fmt = "%u"; break; + case 3: + fmt = "0%o"; break; + case 4: + fmt = "0x%x"; break; + } + + if (32 <= n && n < 127 && (rand() % 4)) fmt = "'%c'"; + printf(n < 8 ? "%d" : fmt, n); + printf(","); + if (pos++ == 8) { + printf("\n"); + pos = 0; + } + else printf(" "); + + printf("};\n"); + } +} + +``` + +As can be seen, there is a slight preference for decimal, and also a character +format is sometimes used, but only if the data is a printable ASCII character. + +When we ran this program, we were almost completely satisfied with the result. +The only problem we had was that the program had chosen an octal representation +for the first word. Since everybody knows what a PDP-11 branch instruction looks +like (everyone knows that the traditional magic word for an executable, `0407`, +is a PDP-11 branch), we changed that to decimal. After checking the size of the +resulting program we saw that it was one byte too long. The limit was 512 bytes, +and our program was 513 bytes. So we changed the word `and` in the comment to +`&&`. + ## Copyright and CC BY-SA 4.0 License: This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved. diff --git a/1991/dds/Makefile b/1991/dds/Makefile index 3c0d91f22..bf62cb45f 100644 --- a/1991/dds/Makefile +++ b/1991/dds/Makefile @@ -85,7 +85,7 @@ CSILENCE= -Wno-implicit-function-declaration # ifeq ($(CC),clang) # -CSILENCE+= -Wno-implicit-int-conversion -Wno-missing-variable-declarations +CSILENCE+= -Wno-implicit-int-conversion -Wno-missing-variable-declarations \ -Wno-pedantic -Wno-poison-system-directorie # CWARN+= -Weverything diff --git a/1991/dds/README.md b/1991/dds/README.md index cd826b25a..434135dc7 100644 --- a/1991/dds/README.md +++ b/1991/dds/README.md @@ -20,6 +20,7 @@ make all ./a.out 2>/dev/null ``` + [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 @@ -31,12 +32,17 @@ memory as a `char *s`. It's now a `char s[]`. Thank you Cody for your assistance! + +NOTE: for `clang` you'll likely have to use the alternate code described below. + ### 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). +file cannot be opened for writing then this program will very likely crash or do +something funny. + +These 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: diff --git a/1991/westley/README.md b/1991/westley/README.md index 2e505d628..89a8e3dbc 100644 --- a/1991/westley/README.md +++ b/1991/westley/README.md @@ -14,7 +14,7 @@ make all ``` [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed a segfault in -this program which prevented it from working. The problem was the read-only +this program which prevented it from working. The problem was that the read-only char array `char *z[]` was being written to. The fix was to change it to `char z[][100]` in two spots (see if you can determine why two places, not one!). Why 100 when the longest string is < 100? Because a shorter value caused strange diff --git a/2006/toledo3/README.md b/2006/toledo3/README.md index 3a4b132e4..169c7ae6a 100644 --- a/2006/toledo3/README.md +++ b/2006/toledo3/README.md @@ -18,7 +18,7 @@ make ``` [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. +display problem in this entry so that it now works 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 diff --git a/2011/richards/Makefile b/2011/richards/Makefile index 1ead51cb3..3b5f81a82 100644 --- a/2011/richards/Makefile +++ b/2011/richards/Makefile @@ -46,7 +46,7 @@ CWARN= -Wall -Wextra ${CSILENCE} # Compiler standard # -CSTD= -std=gnu11 +CSTD= -std=gnu99 # Compiler bit architecture # @@ -65,7 +65,7 @@ CINCLUDE= -include stdlib.h -include string.h -include stdio.h -include ctype.h # Optimization # -OPT= +OPT= # Default flags for ANSI C compilation # diff --git a/2011/richards/README.md b/2011/richards/README.md index 28fbef457..d3c932986 100644 --- a/2011/richards/README.md +++ b/2011/richards/README.md @@ -15,49 +15,64 @@ make ./richards ``` +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) fixed a minor problem +that showed up in both linux and macOS. He notes however that as of this time +this entry does not work with macOS. See [bugs.md](/bugs.md) for more details. +Thank you Cody! + ## Try: ```sh echo '10 9 8 7 6 5 4 3 2 1*p*p*p*p*p*p*p*p*p' | ./richards +echo '64 256 128 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 -interpreter and deemed Worst Abuse of the Rules). -Well, this one does it (expression calculation, that is, not the rule abuse) in a different way. -The author claims that his calculator does just-in-time compilation. -What would you do to prove or disprove his claim without attempting to unravel the source? +Oh no, yet another +[dc](https://en.wikipedia.org/wiki/Dc_(computer_program))-style calculator? (see +[2000/dlowe](/2000/dlowe) using an embedded Perl interpreter and deemed `Worst +Abuse of the Rules`). Well, this one does it (expression calculation, that is, +not the rule abuse) in a different way. The author claims that his calculator +does just-in-time compilation. What would you do to prove or disprove his claim +without attempting to unravel the source? ## Author's remarks: -This is an implementation of the classic UNIX dc command, the reverse-polish +This is an implementation of the classic UNIX +[dc](https://en.wikipedia.org/wiki/Dc_(computer_program)) command, the +[reverse Polish](https://en.wikipedia.org/wiki/Reverse_Polish_notation) 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 comparisons. Wow, you'd think I could've done better in 2K of code. -OH! I forgot to mention! It's a JIT. +OH! I forgot to mention! It's a +[JIT](https://en.wikipedia.org/wiki/Just-in-time_compilation). -Wait, don't stop reading! I know what you're thinking, platform-specific code -is discouraged in IOCCC. But do you see any platform-specific code? There's no -assembler here! This JIT works on a dozen platforms, and the only -platform-specific assumptions it makes are that the stack grows down and -integers are at least 32-bit. +Wait, don't stop reading! I know what you're thinking, platform-specific code is +discouraged in IOCCC. But do you see any platform-specific code? There's no +assembler here! This +[JIT](https://en.wikipedia.org/wiki/Just-in-time_compilation) works on a dozen +platforms, and the only platform-specific assumptions it makes are that the +stack grows down and 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`. - * 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. +* 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`. + +* 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`. + - NOTE from judges: we added these includes in 2023. + +* 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: diff --git a/2011/richards/richards.c b/2011/richards/richards.c index 744d32f9b..76013a390 100644 --- a/2011/richards/richards.c +++ b/2011/richards/richards.c @@ -3,7 +3,10 @@ #endif #include #include -#if !NM +#include +#include +#include +#ifndef NM #include #endif #define vo volatile @@ -24,11 +27,11 @@ #define H 9<<16 #define I case #define J(i) calloc(i,1) -#define W(c) e=(o*)memmove(e,x[(u)c],y[(u)c])+y[(u)c]; +#define W(c) e=memmove(e,x[(u)c],y[(u)c])+y[(u)c]; #define N break; I q char k; q void o; -q unsigned long u; +q int u; q o(*f) (vo o *); q struct { u *a, **R, *m, h, c; @@ -43,7 +46,7 @@ u sk[H]; k *w; o *x[H]; u y[H]; -f *j, *e; +f j, e; u l=256; o g(u v) { @@ -59,7 +62,8 @@ f K(k * p, dt d) { k c, n = 0; f r = (f) e; - W(1) while ((c = *p)) { + W(1) + while ((c = *p)) { switch (c) { I '#': while (*++p != 10); @@ -123,9 +127,9 @@ o T() o rd(u v) { - o *a = 0, **b = &a, **c = b + 24; + o *a = 0, **b = &a, **c = b + 32; x[v] = w; - for (; b < c && (*b < (o *)w || *b > (o *) T || *b == (long) v); b++); + for (; b < c && (*b < (o *)w || *b > (o *) T || *b == &v); b++); if (b == c) { jmp_buf *j = alloca(sizeof(*j)); setjmp(*j); @@ -146,7 +150,7 @@ o re(vo k * rec) } F(d) M--; *M /= M[1]; -} F(p) printf("%lu\n", *M); +} F(p) printf("%d\n", *M); } F(x) u n = *M--; if (!S j[n]) @@ -162,8 +166,8 @@ M++; lx(d); } } -o *lib1[] = { T, T, T, T, T } ; -o *lib2[] = { T, ld, lp, lx, l1 } ; +f *lib1[] = { T, T, T, T, T } ; +f *lib2[] = { T, ld, lp, lx, l1 } ; int main() { @@ -189,10 +193,10 @@ int main() S l = (f *) lib2; S r = (f) T; j = e = -#if NM +#ifdef NM malloc(H); #else - mmap(NULL, H, -1, MAP_ANON | MAP_PRIVATE, -1, 0); + (f)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/2012/endoh2/README.md b/2012/endoh2/README.md index dc6962948..4de0f405d 100644 --- a/2012/endoh2/README.md +++ b/2012/endoh2/README.md @@ -27,25 +27,31 @@ gcc -o e e.c ./e > 271.c ``` +... + ## Try: ```sh -make pi -make e -make everything +./everything.sh ``` ## Judges' remarks: -A pi/e printing quasi-quine in ASCII art with a compressed font in it; -what else to wish for in this program? Virtual machine emulation? +A +[pi](https://en.wikipedia.org/wiki/Pi)/[e](https://en.wikipedia.org/wiki/E_(mathematical_constant)) +printing quasi-[quine](https://en.wikipedia.org/wiki/Quine_(computing) in [ASCII +art](https://en.wikipedia.org/wiki/ASCII_art) with a compressed font in it; what +else to wish for in this program? [Virtual +machine](https://en.wikipedia.org/wiki/Virtual_machine) emulation? ## Author's remarks: Yeah, "Again". Sorry. But I don't feel guilty or uncomfortable. This entry is based on 'over-used themes' such as self reproducing -program and pi or e computation. I know you're tired of them. +program and [pi](https://en.wikipedia.org/wiki/Pi) or +[e](https://en.wikipedia.org/wiki/E_(mathematical_constant))) computation. I +know you're tired of them. But have you ever seen **all-in-one**? @@ -54,57 +60,58 @@ But have you ever seen **all-in-one**? This program generates a new program in the shape of the Greek letter `pi`. Then, the generated program: -- computes 3 digits of pi and prints it as a ASCII-art program that: -- computes 4 digits of pi and prints it as a ASCII-art program that: -- computes 5 digits of pi and prints it as a ASCII-art program that: -- computes 6 digits of pi and prints it as a ASCII-art program that: -- etc. +- computes 3 digits of pi and prints it as an ASCII-art program that: +- computes 4 digits of pi and prints it as an ASCII-art program that: +- computes 5 digits of pi and prints it as an ASCII-art program that: +- computes 6 digits of pi and prints it as an ASCII-art program that: +- ... -One more thing... When you give a command line option "e" to the -first program, the generated one will compute Napier's constant +One more thing... When you give a command line argument `e` to the +first program, the generated one will compute [Napier's +constant](https://en.wikipedia.org/wiki/E_(mathematical_constant))) rather than pi. ### Obfuscation -This program itself is in the shape of a spigot. This is derived -from analogy with "spigot algorithm" which infinitely computes the -value of a mathematical constant such as `pi` or `e`. +This program itself is in the shape of a +[spigot](https://en.wikipedia.org/wiki/Tap_(valve)). This is derived from +analogy with [spigot algorithm](https://en.wikipedia.org/wiki/Spigot_algorithm) +which infinitely computes the value of a mathematical constant such as +[pi](https://en.wikipedia.org/wiki/Pi) or +[e](https://en.wikipedia.org/wiki/E_(mathematical_constant)). - +The two sets of programs, `314*.c` and `271*.c`, are almost the same +except their shape and constant computational part. I tailored the +common part to parse in both shapes (`3.14...` and `2.71...`), by +tweaking the computational order and adding meaningless code fragments. -The two sets of programs, 314\*.c and 271\*.c, are almost the same -except its shape and constant computation part. I tailored the -common part to parse in both shapes ("3.14..." and "2.71..."), by -tweaking the computation order and adding meaningless code fragment. - -On the other hand, to make it fit inside one screen (80 x 25), my -program is shortened properly, more than it looks. (As you may -know, Quine needs to make its program size doubled.) -For example, this program involves 3x5 bitmap font data of ten -characters ('0' -- '9'), as just 20 bytes: "G1%xJ{;Q7wunmuGuu%uu". -We can decode character n as `275*s[n+10] - 8*s[n] - 8`. I solved the -system of Bezout's identities to find the magic string, with the -aid of a brute force. See `find-font-table.rb` in detail. - - +On the other hand, to make it fit inside one screen (80 x 25), my program is +shortened properly, more than it looks. (As you may know, +[quines](https://en.wikipedia.org/wiki/Quine_(computing)) need to make its +program size doubled.) For example, this program involves 3x5 bitmap font data +of ten characters (`0` -- `9`), as just 20 bytes: `G1%xJ{;Q7wunmuGuu%uu`. We +can decode character `n` as `275*s[n+10] - 8*s[n] - 8`. I solved the system of +[Bézout's identity](https://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity) to +find the magic string, with the aid of a brute force. See `find-font-table.rb` +in detail. I used many other tricks for short coding. -I'm sorry that many ASCII-art-style winning entries of IOCCCs -ignore preprocessor directives. In my program, #include is a part -of ASCII-art with comment padded. +I'm sorry that many ASCII-art-style winning entries of +[IOCCC](https://www.ioccc.org/years.html) ignore [C preprocessor +directives](https://en.wikipedia.org/wiki/C_preprocessor). In my program, +`#include` is a part of ASCII-art with comments padded. These design requirements made my program well-obfuscated willy-nilly. ### Portability -I expect it to work in any major environment and C compiler. -To build with no warning, it requires two C99 features: string -literal more than 509 characters and omissible return in main -function. In fact, recent compilers with "-std=c99 -Wall -W --Wextra -pedantic" would say nothing. +I expect it to work in any major environment and C compiler. To build with no +warning, it requires two C99 features: string literal more than 509 characters +and not requiring a return in `main()` function. In fact, recent compilers with +`-std=c99 -Wall -W -Wextra -pedantic` would say nothing. gcc -std=c99 -Wall -W -Wextra -pedantic spigot.c clang -std=c99 -Wall -W -Wextra -pedantic spigot.c @@ -141,7 +148,7 @@ etc... You can do `make everything` for the process (with no `cat`). Note: The executable may return a failure (non-zero) exit status -unless -std=c99 option is given. +unless `-std=c99` option is given. ## Copyright and CC BY-SA 4.0 License: diff --git a/2012/endoh2/endoh2.c b/2012/endoh2/endoh2.c index 575670a1a..b9d87aaff 100644 --- a/2012/endoh2/endoh2.c +++ b/2012/endoh2/endoh2.c @@ -1,4 +1,4 @@ -#include /******** SpigotQuine -- usage: ./spigot [pi or e] ********/ +#include /******** SpigotQuine -- usage: ./endoh2 [pi or e] ********/ char*s="G1%%xJ{;Q7wunmuGuu%%uu#include/*Spigot_Quine*/#include/*_IOCCC2012_*/int*e," "i,j,k,n" ";char*q" ",*a,*d,*z,*p=%s%c;" "int" "%cmain(){a=calloc(" "1,1e4+n*2);;for(*" diff --git a/2012/endoh2/everything.sh b/2012/endoh2/everything.sh new file mode 100755 index 000000000..69ba30276 --- /dev/null +++ b/2012/endoh2/everything.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +make everything || exit 1 + +run() +{ + local program="$1" + echo "" 1>&2 + echo -n "$ ./${program}" 1>&2 + sleep 2 + "./${program}" | less -K -e +} +echo "running everything with $(type -P less): " 1>&2 +echo 1>&2 +run pi +run 314 +run 3141 +run 31415 +run 314159 +run 3141592 +run 31415926 +run 314159265 +run 3141592653 +run 31415926535 +run e 271 +run 2718 +run 27182 +run 271828 +run 2718281 +run 27182818 +run 271828182 +run 2718281828 +run 27182818284 diff --git a/2012/grothe/README.md b/2012/grothe/README.md index 76aafed11..267a03b77 100644 --- a/2012/grothe/README.md +++ b/2012/grothe/README.md @@ -1,13 +1,11 @@ # Most conspiratorial - Aaron Grothe - 2205 South 51st Street - Omaha, NE 68106 - US - +Aaron Grothe +US + - David Madore - +David Madore + ## To build: @@ -17,13 +15,14 @@ make ## To run: -To create a shared secret shared among M people with N+1 needed to reconstruct: +To create a shared secret shared among `M` people with `N+1` needed to reconstruct: ```sh -./grothe -secret 1-/dev/urandom 2-/dev/urandom ... N-/dev/urandom 1+shared1 2+shared2 ... M+sharedM +./grothe -secret 1-/dev/urandom 2-/dev/urandom ... \ + N-/dev/urandom 1+shared1 2+shared2 ... M+sharedM ``` -To reconstruct the original (an arbitrary combination of N+1 or +To reconstruct the original (an arbitrary combination of `N+1` or more shared files with their proper numbers): ```sh @@ -42,28 +41,27 @@ more shared files with their proper numbers): ## Judges' remarks: -Also known as Best abuse of the judging process. +Also known as 'Best abuse of the judging process'. -The IOCCC 2012 submission page didn't enforce the 2048 meaningful -character limit. This entry, as submitted, weighed in at 2222 chars -but was, luckily for it, extremely easy to bring down below the -limit. There were a number of strings that when concatenated allowed -the program to slide under the limit. +The IOCCC 2012 submission page didn't enforce the 2048 meaningful character +limit. This entry, as submitted, weighed in at 2222 chars but lucky for it, it +was extremely easy to bring down below the limit. There were a number of +strings that when concatenated allowed the program to slide under the limit. -It was clear to the judges that the extra size was an entry -beautification step. Had it not, this entry would have been -rejected in round 0. +It was clear to the judges that the extra size was an entry beautification step. +Had it not been, this entry would have been rejected in round 0. -The judges also took some liberty obfuscating this entry a litte more. +The judges also took some liberty obfuscating this entry a little more. How does this entry work? The only place multiplication is used is -to perform the atoi conversion. +to perform the `atoi()` conversion. ## Author's remarks: -**Description** +### Description -This program implements a version of Shamir's Secret Sharing. Shamir's Secret +This program implements a version of [Shamir's Secret +Sharing](http://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing). Shamir's Secret Sharing allows you to encrypt a file into N parts where it will take M parts to recreate the original file. E.g. you can split the secret recipe for Crystal Pepsi into 3 parts and require two of them be available to extract the original recipe. @@ -72,18 +70,19 @@ Actually surprisingly useful for an IOCCC entry :-) ### Usage -To share a secret +To share a secret. E.g. -file to be shared - cookie\_recipe.txt +File to be shared - [cookie_recipe.txt](cookie_recipe.txt). number of pieces - 2 + file to be shared total number of pieces created by program 4 pieces needed to reassemble recipe 3 or greater ### Example usage -To share secret into 4 pieces of which at least 3 will be needed to get back the recipe: +To split a secret into 4 pieces of which at least 3 will be needed to get it (in +this case a recipe) back: ```sh ./grothe \ @@ -92,7 +91,7 @@ To share secret into 4 pieces of which at least 3 will be needed to get back the 1+cookie_piece1.dat 2+cookie_piece2.dat 3+cookie_piece3.dat 4+cookie_piece4.dat ``` -To put recipe back together using 1, 2 and 4th piece: +To put recipe back together using the first, second and fourth pieces: ```sh ./grothe \ @@ -102,25 +101,43 @@ To put recipe back together using 1, 2 and 4th piece: ### Limitations -* program is limited to 256 input and output files and will slow down dramatically when you get past 20-50 inputs and outputs +The program is limited to 256 input and output files and will slow down +dramatically when you get past 20-50 inputs and outputs. ### Obfuscations -* nothing is done consistently throughout the program E.g i+=1, i=i+1, i++ and ++i are all used in the program. The mark of true code buggery. - "A foolish consistency is the hobgoblin of little minds" - Ralph Waldo Emerson -* uses the most powerful obfuscation of all "Math". "Any sufficiently advanced cryptography is indistinguasble from magic" - Apologies to Arthur C. Clarke -* shadows variables by using brackets in main program to create local copies of variables that are the same as global scope variables. -Wshadow should probably be a part of -Wall in gcc -* uses array\_index[array\_name] instead of array\_name[array\_index] in several places. Still don't know why C continues to allow this -( error strings are encoded with offsets that are also used to select them in the case statement. All strings are located in one function for easy localization -* liberal use of octal numbers, hexadecimal numbers and regular decimal numbers throughout program +* nothing is done consistently throughout the program E.g `i+=1`, `i=i+1`, `i++` +and `++i` are all used in the program. The mark of true code buggery: "A +foolish consistency is the hobgoblin of little minds." - [Ralph Waldo +Emerson](https://en.wikipedia.org/wiki/Ralph_Waldo_Emerson) + +* uses the most powerful obfuscation of all "Math". "Any sufficiently advanced +cryptography is indistinguishable from magic." - Apologies to [Arthur C. +Clarke](https://en.wikipedia.org/wiki/Arthur_C._Clarke) + +* shadows variables by using brackets in main program to create local copies of +variables that are the same as global scope variables. `-Wshadow` should +probably be a part of `-Wall` in gcc. + +* uses `array_index[array_name]` instead of `array_name[array_index]` in several +places. Still don't know why C continues to allow this (error strings are +encoded with offsets that are also used to select them in the case statement. +All strings are located in one function for easy localization). + +* liberal use of octal numbers, hexadecimal numbers and regular decimal numbers +throughout program. + * variables and function names are semi-random and upper and lower case characters are used -* use of #defines from stdio.h, stdlib.h for values \_STDIO\_H and EXIT\_SUCCESS used to represent 1 and 0 respectively in the program -* arrays only need to be 256x256 most are set to greater values than they need to be so trying to figure it out can be a bit tough +* use of `#define`s from `stdio.h`, `stdlib.h` for values `_STDIO_H` and +`EXIT_SUCCESS` used to represent 1 and 0 respectively in the program. + +* arrays only need to be 256x256 but most are set to greater values than they +need to be so trying to figure it out can be a bit tough. ### References -* Shamir's Secret Sharing - http://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing -* David Madore's implementation of Shamir's Secret Sharing - http://www.madore.org/~david/programs/programs-1.36.html -* Steve's Recipe Database - source for the $25k Cookie Recipe - http://recipes.stevex.net/ +* David Madore's implementation of Shamir's Secret Sharing - +* Steve's Recipe Database - source for the $25k Cookie Recipe - ## Copyright and CC BY-SA 4.0 License: diff --git a/2012/hamano/README.md b/2012/hamano/README.md index 442e46040..4fd1cc163 100644 --- a/2012/hamano/README.md +++ b/2012/hamano/README.md @@ -1,7 +1,7 @@ # Most elementary use of C - Silver award - Tsukasa Hamano - +Tsukasa Hamano + ## To build: @@ -21,7 +21,11 @@ make ./hamano < README.md > hint.pdf ``` -You can read output.pdf with PDF reader acroread hint.pdf or evince hint.pdf. +You can read `hint.pdf` with a PDF reader like `acroread hint.pdf` or `evince +hint.pdf`. With macOS you can do `open hint.pdf` which by default will open +`Preview.app`. You may of course use your pdf view to open the file directly +instead. + To deobfuscate: @@ -39,7 +43,7 @@ cc -Wno-implicit-function-declaration -xc hello.pdf -o hello2 ./hello3 ``` -## Judges' remarks +## Judges' remarks: This entry treads into a new territory for IOCCC - generating PDF files. @@ -63,32 +67,30 @@ So what do those flags really mean? The [Dancing men algorithm][1] might be useful. -Don't forget to take a look at the generated PDF, perhaps you might even want +Don't forget to take a look at the generated PDF. Perhaps you might even want to compile the output with a C compiler. When you run it, what does it output? -## Author's remarks +## Author's remarks: -This program obfuscate text file into PDF file with Dancing men -algorithm. +This program obfuscate text file into PDF file with [Dancing men +algorithm](http://en.wikipedia.org/wiki/The_Adventure_of_the_Dancing_Men). - - -Probably, the output PDF file is compliant with PDF 1.3. And also +Probably, the output PDF file is compliant with PDF 1.3 and it's also available to compile as C code. -I've been tested with GCC 4.7 and Clang 3.0 on Linux, and following -PDF Reader: +I've tested it with GCC 4.7 and Clang 3.0 with Linux, and the following +PDF Readers: - * Adobe Acrobat Reader - * Evince - * Ghostscript - * Xpdf +* Adobe Acrobat Reader +* Evince +* Ghostscript +* Xpdf ### Obfuscations -This program is obfuscated by using classical methods. -But can you find out the embedded font from fragmented glyph? +This program is obfuscated by using classical methods. But can you find the +embedded font in the fragmented glyph? ## Copyright and CC BY-SA 4.0 License: diff --git a/2012/hou/.gitignore b/2012/hou/.gitignore index 186d1661b..b839123df 100644 --- a/2012/hou/.gitignore +++ b/2012/hou/.gitignore @@ -1,3 +1,4 @@ hou hou.html remarks.htm +remarks.htm diff --git a/2012/hou/README.md b/2012/hou/README.md index 9b1cc0c0e..241889432 100644 --- a/2012/hou/README.md +++ b/2012/hou/README.md @@ -1,8 +1,8 @@ # Most useful obfuscation - Qiming Hou - - +Qiming Hou + + ## To build: @@ -42,54 +42,93 @@ start hou.htm ## Judges' remarks: -What a versatile entry! It can be used to check the size of IOCCC entries *and* to publish them as HTML. +What a versatile entry! It can be used to check the size of IOCCC entries *and* +to publish them as HTML. -For extra credit: what is the meaning of the number 2321237? +For extra credit: what is the meaning of the number `2321237`? ## Author's remarks: ### Disclaimer -The reviewer may have already noticed that the 2nd page of this program is a dense blob, which is discouraged by the contest rules. We wish to point out that a majority of state-of-art programming editors support syntax highlighting, which should be enabled when reading this entry. Anticipating that the reviewer's preferred color setting may produce a suboptimal visual effect, a few syntax files is provided to highlight the source code under an author-provided setting, using the submitted program itself. Syntax highlighting would also visually improve the 3rd page. +The reviewer may have already noticed that the 2nd page of this program is a +dense blob, which is discouraged by the contest rules. We wish to point out that +a majority of state-of-art programming editors support syntax highlighting, +which should be enabled when reading this entry. Anticipating that the +reviewer's preferred color setting may produce a suboptimal visual effect, a few +syntax files is provided to highlight the source code under an author-provided +setting, using the submitted program itself. Syntax highlighting would also +visually improve the 3rd page. -The code may throw a few warnings due to formatting constraints. The author did try to remove warnings under gcc and Visual Studio, though. +The code may throw a few warnings due to formatting constraints. The author did +try to remove warnings under gcc and Visual Studio, though. -The author does not own the original anime series where the embedded ASCII arts come from. For comparison, original non-ASCII art depictions of the relevant characters and objects can be found by googling the embedded text messages. +The author does not own the original anime series where the embedded ASCII arts +come from. For comparison, original non-ASCII art depictions of the relevant +characters and objects can be found by googling the embedded text messages. ### Syntax files -The syntax file consists of a number of rewriting rules. Each rule consists of a regular expression, a space, a format string, and a newline. All text matching the regular expression would be replaced by the format string. In case of a conflict, rules appearing earlier would take precedence. One can refer to the original text in the format string using "%s". Other "%" characters in the format string must be escaped with another "%". The space character can be used in the regular expression by escaping it with [] or "". +The syntax file consists of a number of rewriting rules. Each rule consists of a +regular expression, a space, a format string, and a newline. All text matching +the regular expression would be replaced by the format string. In case of a +conflict, rules appearing earlier would take precedence. One can refer to the +original text in the format string using `%s`. Other `%` characters in the +format string must be escaped with another `%`. The space character can be used +in the regular expression by escaping it with `[]` or `""`. -The following regular expression operators is supported: +The following regular expression operators are supported: - () [] * + ? | "" +``` +() [] * + ? | "" +``` For example, one can use the following expression to match a certain declaration statement in hou.c: +``` "char"[ *]*[a-zA-Z_][0-9a-zA-Z_]*[ ]*((=[0-9a-zA-Z_ ]+)|(\[[0-9a-zA-Z_ ]*\]))?[ ]*(,[ *]*[a-zA-Z_][0-9a-zA-Z_]*[ ]*((=[0-9a-zA-Z_ ]+)|(\[[0-9a-zA-Z_ ]*\]))?[ ]*)*; +``` -The regex engine is also algorithmically efficient. To illustrate the point, ansi.txt contains a pathological expression [2] that guarantees a hang for the competing Perl engine while matching itself. Try to compare these two engines: +The regex engine is also algorithmically efficient. To illustrate the point, +[ansi.txt](ansi.txt) contains a pathological expression [2] that guarantees a +hang for the competing Perl engine while matching itself. Try to compare these +two engines: +```sh ./hou ansi.txt ansi.txt perl patho.pl < ansi.txt +``` + +### Limitations Finally, there are a few limitations... - -- The only escape sequence supported is \n and it doesn't work in []. -- The maximum file/rule size is a linear function of the hard-coded constant M. +- The only escape sequence supported is `\n` and it doesn't work in `[]`. +- The maximum file/rule size is a linear function of the hard-coded constant `M`. - Single-character matches at the end of file may be missed. -- The operator | doesn't obey precedence rules and some extra ()s may be required. +- The operator `|` doesn't obey precedence rules and some extra `()`s may be required. - Incorrect syntax files are not tolerated. - The program relies on ASCII. ### Why obfuscated -The first layer of obfuscation comes from the challenge of embedding a large ASCII art in a dense blob. The entire art is composed using only keywords, strings and character constants. That results in a number of otherwise useless defines and quite a number of unconventionally written constants. While the preprocessor may remove the former, the later would remain regardless of beautification and preprocessing. +The first layer of obfuscation comes from the challenge of embedding a large +ASCII art in a dense blob. The entire art is composed using only keywords, +strings and character constants. That results in a number of otherwise useless +defines and quite a number of unconventionally written constants. While the +preprocessor may remove the former, the later would remain regardless of +beautification and preprocessing. -The second layer of obfuscation comes from the need to squeeze a reasonably powerful regex engine into the remaining area that isn't occupied by excessive keywords and useless constants. To achieve this, the regex compiler is written using the same threaded virtual machine [1] that parses the regex. Due to compiler limitations, the generated VM code also ends up obscured by a large amount of spaghetti branches and virtual thread creations. Finally, the VM in [1] is extended to track multiple expression matches for the actual formatting. +The second layer of obfuscation comes from the need to squeeze a reasonably +powerful regex engine into the remaining area that isn't occupied by excessive +keywords and useless constants. To achieve this, the regex compiler is written +using the same threaded virtual machine [1] that parses the regex. Due to +compiler limitations, the generated VM code also ends up obscured by a large +amount of spaghetti branches and virtual thread creations. Finally, the VM in +[1] is extended to track multiple expression matches for the actual formatting. -As an extra tweak, the text message actually does something useful. Remove the "Make a contract with me" catch line and the program would cease to function. +As an extra tweak, the text message actually does something useful. Remove the +"Make a contract with me" catch line and the program would cease to function. ### References diff --git a/2012/kang/README.md b/2012/kang/README.md index 56a09a2e5..d0880a685 100644 --- a/2012/kang/README.md +++ b/2012/kang/README.md @@ -1,7 +1,8 @@ # Best short program - Seonghoon Kang - +Seonghoon Kang + + ## To build: @@ -27,7 +28,8 @@ echo "shest'" | ./kang [Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) changed the code to accept the proper German for four 'vier' where before it was spelt with the -sound of V (fier not vier). Thank you Cody! +sound of V (fier not vier). But was this a bug or a feature? He's on the fence +here but he went ahead and did it anyway as it seems useful. Thank you Cody! ## Judges' remarks: @@ -73,7 +75,7 @@ It does *not* accept some spelt numbers, which I found mostly irrelevant: This program is quite portable, only requiring the following: * The signature `int main(int, int)` should be accepted by the linker. (Original - version only) + version only). * `char` should be at least 8 bits long (as dictated by the standard), `int` should be at least 32 bits long, `long long` should be at least 64 bits long. * Both the compiler and execution environment should use an ASCII-compatible @@ -120,17 +122,21 @@ Other obfuscations are more subtle: But the most important obfuscation is the clever construction of lookup table. The program uses 11 different characters required for recognizing 22 lexemes: +``` zero one tw- th(i)r- fo(u)r- fi- six- seven- eigh- nin- ten eleven twelve hundred(s) thousand(s) million(s) billion(s) trillion(s) a and -teen -ty +``` So that they are internally represented as like: +``` r n tw- tr- fr- f- s- sn- g- nn- tn ln twl nr(s) tsan(s) lln(s) blln(s) trlln(s) a an -tn -ty +``` The stemmer recognizes the longest matching prefix, so every lexeme can be recognized by at most three characters (e.g. `trl` instead of `trlln`). This is @@ -151,6 +157,8 @@ Having said this important trick, other details should be relatively easier to follow. The order of lookup table, for example, is very important, and the biggest constant 6177 is not arbitrarily chosen. +More spoilers can be found at + ### Acknowledgement The cleaner (size-optimized) version of this program was originally published diff --git a/2012/konno/README.md b/2012/konno/README.md index cd3333a37..28ca59ab2 100644 --- a/2012/konno/README.md +++ b/2012/konno/README.md @@ -1,8 +1,8 @@ # Best one liner - Taketo Konno - Tokyo, Japan - +Taketo Konno +Japan + ## To build: @@ -26,7 +26,7 @@ NOTE: N is an integer from 0 to 255. ### Alternate code -An alternate version of this entry, `konno_alt.c`, is provided. +An alternate version of this entry, [konno.alt.c](konno.alt.c), is provided. This alternate code is an unobfuscated version of the winning code. To compile this alternate version: @@ -60,7 +60,7 @@ Try: ./konno 165 ``` -There are 256 (from 0 to 255) possible rules. +There are 256 (from 0 through 255) possible rules. ### Obfuscation @@ -70,7 +70,7 @@ This program uses bit operations. I think 7&O<>!o+29 ``` -is an intersting operation. This isn't equal to +is an interesting operation. This isn't equal to ```c 7&O>>29 @@ -80,7 +80,7 @@ operation. What is the operation doing? ### Limitation -This program assumes that the size of int is 4. +This program assumes that the size of `int` is 4. ## Copyright and CC BY-SA 4.0 License: diff --git a/2012/omoikane/README.md b/2012/omoikane/README.md index ead0d5d19..a2d5964d3 100644 --- a/2012/omoikane/README.md +++ b/2012/omoikane/README.md @@ -1,8 +1,8 @@ # Most surreptitious - Don Yang - - +Don Yang + + ## To build: @@ -36,81 +36,90 @@ cc -o output output.c ## Judges' remarks: -The judges have nothing to add that has not already been written -about in the `spoiler.html`` file! :-) +The judges have nothing to add that has not already been written about in the +[spoiler.html](spoiler.html) (requires JavaScript) file! :-) ## Author's remarks: ### Usage -Nyaruko is a binary to text filter. Given some input on stdin, -Nyaruko will produce C code that reproduces this input on stdout: +`Nyaruko` is a binary to text filter. Given some input on stdin, +`Nyaruko` will produce C code that reproduces this input on stdout: - ./nyaruko < original.bin > output.c - gcc output.c -o output - ./output > regenerated.bin +```sh +./nyaruko < original.bin > output.c +gcc output.c -o output +./output > regenerated.bin +``` Output is encrypted, but both key and data are included in the output. To separate the key from the data, run these commands: +```sh bash output.c > key.c perl output.c > data.c +``` -The key-less data.c still compiles, but produces a different message +The key-less `data.c` still compiles, but produces a different message on stdout instead of the original input. This message is a hint to why the code is formatted the way it is. To combine the key and data, concatenate them together in either order: +```sh cat key.c data.c > output.c cat data.c key.c > output.c +``` -By default, Nyaruko generates a unique random key for every message, -using /dev/urandom as the seed. If given an extra command line -argument, Nyaruko will seed using that file instead of /dev/urandom: +By default, `Nyaruko` generates a unique random key for every message, +using `/dev/urandom` as the seed. If given an extra command line +argument, `Nyaruko` will seed using that file instead of `/dev/urandom`: - ./nyaruko seed.txt < input.bin > output.c +```sh +./nyaruko seed.txt < input.bin > output.c +``` This makes the output key deterministic, allowing the same key to be shared across different files. On operating systems that do not have -/dev/urandom, users should always specify this extra seed argument to +`/dev/urandom`, users should always specify this extra seed argument to avoid deterministic keys. ### Features -Implementation details that makes Nyaruko more obfuscated than usual +Implementation details that make `Nyaruko` more obfuscated than usual programs: - * Nyaruko recycles variables and buffers to reduce internal state. - The variable names are also carefully chosen for mixed-case - madness. - * Nyaruko employs some preprocessor magic to share much of the same - code and state between the encoder and decoder, and to increase - occurrences of smileys ;) +* `Nyaruko` recycles variables and buffers to reduce internal state. + The variable names are also carefully chosen for mixed-case + madness. +* `Nyaruko` employs some preprocessor magic to share much of the same + code and state between the encoder and decoder, and to increase + occurrences of smileys ;) Output code has these features: - * Fits nicely under 80 columns, and does not contain any trigraphs. - * Uses a fairly efficient encoding scheme, better than uuencode for - files larger than ~13K, and better than base64 for files larger - than 20K. - * Encryption with ISAAC, a cryptographically secure pseudorandom - number generator. - * Trivial 3 language polyglot. +* Fits nicely under 80 columns, and does not contain any trigraphs. +* Uses a fairly efficient encoding scheme, better than `uuencode` for + files larger than ~13K, and better than `base64` for files larger + than 20K. +* Encryption with [ISAAC](https://en.wikipedia.org/wiki/ISAAC_(cipher)), a +cryptographically secure pseudorandom number generator. +* Trivial 3 language polyglot. -Code layout is meant to resemble Nyaruko, also known as Nyarlathotep, -the Crawling Chaos. The most obvious thing to do with chaos is to -make a random number generator, and the most obvious thing to do with -a random number generator is to make one-time-pads for encryption. +Code layout is meant to resemble +[Nyaruko](https://en.wikipedia.org/wiki/Nyarlathotep), also known as +`Nyarlathotep`, the Crawling Chaos. The most obvious thing to do with chaos is +to make a random number generator, and the most obvious thing to do with a +random number generator is to make one-time-pads for encryption. ### Compatibility -Nyaruko has these environment dependencies: +`Nyaruko` has these environment dependencies: - * Requires ASCII character set. - * Assumes sizeof(unsigned int) == 4. - * Best viewed with tab stops set to 8 spaces. +* Requires ASCII character set. +* Assumes `sizeof(unsigned int) == 4`. +* Best viewed with tab stops set to 8 spaces. Output code has the same dependencies, with the additional requirement that the compiler must support arbitrarily long string @@ -118,23 +127,24 @@ literals. Maximum input size that can be encoded while still producing standard-compliant output is ~276 bytes for C89, and ~3168 bytes for C99. -Nyaruko has been to verified to work with these compiler/OS +`Nyaruko` has been to verified to work with these compiler/OS combinations: - * gcc 4.4.5 on Linux (32bit and 64bit) - * clang 3.1 on Windows (Cygwin) - * gcc 4.5.3 on Windows (Cygwin) - * gcc 4.5.3 on Windows (MingW) - * gcc 4.3.5 on JSLinux - * tcc 0.9.25 on JSLinux +* gcc 4.4.5 on Linux (32bit and 64bit) +* clang 3.1 on Windows (Cygwin) +* gcc 4.5.3 on Windows (Cygwin) +* gcc 4.5.3 on Windows (MingW) +* gcc 4.3.5 on JSLinux +* tcc 0.9.25 on JSLinux Note that on MingW, stdin and stdout are not opened in binary mode by -default, this means Nyaruko may not faithfully encode files on MingW. +default, this means `Nyaruko` may not faithfully encode files on MingW. ### Extra files -spoiler.html - Contains full recording of how the code went from -blank state to an obfuscated program, gzipped to fit under 1MB. +[spoiler.html](spoiler.html) - Contains full recording of how the code went from +blank state to an obfuscated program, gzipped to fit under 1MB. Requires +JavaScript. ## Copyright and CC BY-SA 4.0 License: diff --git a/2012/tromp/README.md b/2012/tromp/README.md index f23fb04dd..0e6c35a51 100644 --- a/2012/tromp/README.md +++ b/2012/tromp/README.md @@ -1,31 +1,39 @@ # Most functional -John Tromp - - +John Tromp + + ## To build: - make all # On a 64-bit machine (default) +```sh +make all # On a 64-bit machine (default) - make tromp32 # On a 32-bit machine +make tromp32 # On a 32-bit machine +``` ## To run: - ./tromp [-b] +```sh +./tromp [-b] +``` - NOTE: Substitute ./tromp32 for ./tromp everywhere below if on a 32-bit machine +Use `./tromp32` as you would `./tromp` if on a 32-bit machine. ## To run: - cat ascii-prog.blc data | ./tromp -b - cat binary-prog.Blc data | ./tromp +```sh +cat ascii-prog.blc data | ./tromp -b +cat binary-prog.Blc data | ./tromp +``` ## Try: - (cat hilbert.Blc; echo -n 1234) | ./tromp - (cat oddindices.Blc; echo; cat primes.blc | ./tromp -b) | ./tromp - cat primes.blc | ./tromp -b | ./primes.pl +```sh +(cat hilbert.Blc; echo -n 1234) | ./tromp +(cat oddindices.Blc; echo; cat primes.blc | ./tromp -b) | ./tromp +cat primes.blc | ./tromp -b | ./primes.pl +``` ### Selected Judges Remarks: @@ -35,91 +43,116 @@ are more obfuscated than the entry itself. ## Author's remarks: This program celebrates the close connection between obfuscation and conciseness, -by implementing the most concise language known, Binary Lambda Calculus (BLC). +by implementing the most concise language known, [Binary Lambda Calculus +(BLC)](https://tromp.github.io/cl/Binary_lambda_calculus.html). -BLC was developed to make Algorithmic Information Theory, the theory of smallest programs, -more concrete. It starts with the simplest model of computation, the lambda calculus, -and adds the minimum amount of machinery to enable binary input and output. +[BLC](https://tromp.github.io/cl/Binary_lambda_calculus.html) was developed to +make [Algorithmic Information +Theory](https://en.wikipedia.org/wiki/Algorithmic_information_theory), the +theory of smallest programs, more concrete. It starts with the simplest model of +computation, the [lambda +calculus](https://en.wikipedia.org/wiki/Lambda_calculus), and adds the minimum +amount of machinery to enable binary input and output. -More specifically, it defines a universal machine, which, from an input stream of bits, -parses the binary encoding of a lambda calculus term, applies that to the remainder -of input (translated to a lazy list of booleans, -which have a standard representation in lambda calculus), -and translates the evaluated result back into a stream of bits to be output. +More specifically, it defines a universal machine, which, from an input stream +of bits, parses the binary encoding of a [lambda +calculus](https://en.wikipedia.org/wiki/Lambda_calculus) term, applies that to +the remainder of input (translated to a lazy list of +[booleans](https://en.wikipedia.org/wiki/Boolean_algebra), which have a standard +representation in lambda calculus), and translates the evaluated result back +into a stream of bits to be output. -Lambda is encoded as 00, application as 01, and the variable bound by the n'th -enclosing lambda (denoted n in so-called De Bruijn notation) as 1^{n}0. -That's all there is to BLC! +Lambda is encoded as 00, application as 01, and the variable bound by the `n`th +enclosing lambda (denoted `n` in so-called [De Bruijn +notation](https://en.wikipedia.org/wiki/De_Bruijn_notation)) as `1^{n}0`. +That's all there is to +[BLC](https://tromp.github.io/cl/Binary_lambda_calculus.html)! -For example the encoding of lambda term S = \x \y \z (x z) (y z), -with De Bruijn notation \ \ \ (3 1) (2 1), -is 00 00 00 01 01 1110 10 01 110 10 +For example the encoding of lambda term `S = \x \y \z (x z) (y z)`, +with [De Bruijn notation](https://en.wikipedia.org/wiki/De_Bruijn_notation) `\ \ +\ (3 1) (2 1)`, is `00 00 00 01 01 1110 10 01 110 10`. -In the closely related BLC8 language, IO is byte oriented, -translating between a stream of bytes and a list of length-8 lists of booleans. +In the closely related +[BLC8](https://tromp.github.io/cl/Binary_lambda_calculus.html#BLC8:_byte_sized_I.2FO) +language, IO is byte oriented, translating between a stream of bytes and a list +of length-8 lists of [booleans](https://en.wikipedia.org/wiki/Boolean_algebra). The submission implements the universal machine in the most concise manner conceivable. -It lacks #defines and #includes, and compiles to a (stripped) executable of under 6K in size. +It lacks `#defines` and `#includes`, and compiles to a (stripped) executable of +under 6K in size. -Without arguments, it runs in byte mode, using standard in- and output. +Without arguments, it runs in byte mode, using standard input and output. With one (arbitrary) argument, it runs in bit mode, using only the least significant -bit of input, and using characters '0' and '1' for output. +bit of input, and using characters `0` and `1` for output. The program uses the following exit codes: + +``` 0: OK; result is a finite list 5: Out of term space 6: Out of memory 1,2,3,4,8,9: result not in list form +``` -The size of the term space is fixed at compile time with -DA +The size of the term space is fixed at compile time with `-DA`. -A half byte `cat' -================= +### A half byte `cat` -The shortest (closed) lambda calculus term is \x x (\ 1 in De Bruijn notation) -which is the identity function. When its encoding 0010 is fed -into the universal machine, it will simply copy the input to the output. -(well, not that simply, since each byte is smashed to bits and rebuilt from scratch) -Voila: a half byte cat: +The shortest (closed) lambda calculus term is `\x x (\ 1` in [De Bruijn +notation](https://en.wikipedia.org/wiki/De_Bruijn_notation)) which is the +identity function. When its encoding `0010` is fed into the universal machine, +it will simply copy the input to the output. (well, not that simply, since each +byte is smashed to bits and rebuilt from scratch) Voila: a half byte cat: - echo " Hello, world" | ./tromp - Hello, world +```sh +$ echo " Hello, world" | ./tromp +Hello, world +``` Since the least significant 4 bits of the first byte are just arbitrary padding -that is ignored by the program, -any character from ASCII 32 (space) through 47 (/) will do, e.g.: +that is ignored by the program, any character from ASCII 32 (space) through 47 +(`/`) will do, e.g.: - echo "*Hello, world" | ./tromp - Hello, world +```sh +$ echo "*Hello, world" | ./tromp +Hello, world +``` -Bad programs -============ + + +### Bad programs If the input doesn't start with a valid program, that is, if the interpreter reaches end-of-file during program parsing, -it will crash in some way: +it will crash in some way. E.g. the following might dump core: - echo -n "U" | ./tromp - Segmentation fault +```sh +echo -n "U" | ./tromp +``` Furthermore, the interpreter requires the initial encoded lambda term to be closed, -that is, variable n can only appear within at least n enclosing lambdas. -For instance the term \ 5 is not closed, -causing the interpreter to crash when looking into a null-pointer environment: +that is, variable `n` can only appear within at least `n` enclosing lambdas. +For instance the term `\ 5` is not closed, causing the interpreter to crash when +looking into a null-pointer environment: - echo ">Hello, world" | ./tromp - Segmentation fault +```sh +echo ">Hello, world" | ./tromp -Since these properties can be checked when creating BLC programs, +``` + +will likely dump core. + +Since these properties can be checked when creating +[BLC](https://tromp.github.io/cl/Binary_lambda_calculus.html) programs, the interpreter doesn't bother checking for it. -A Self Interpreter -================== +### A Self Interpreter -The BLC universal machine may be small at 650 bytes of C -(952 bytes including layout), but written +The [BLC](https://tromp.github.io/cl/Binary_lambda_calculus.html) universal +machine may be small at 650 bytes of C (952 bytes including layout), but written as a self interpreter in BLC it is downright minuscule at 232 bits (29 bytes): +``` 01010001 10100000 00010101 @@ -140,9 +173,11 @@ as a self interpreter in BLC it is downright minuscule at 232 bits (29 bytes): 11110111 11001111 01110110 00011001 00011010 00011010 +``` The byte oriented BLC8 version weighs in at 43 bytes (shown in hexadecimal). +``` 19468 05580 05f00 @@ -156,14 +191,18 @@ The byte oriented BLC8 version weighs in at 43 bytes (shown in hexadecimal). 0b7fb 00cf6 7bb03 91a1a - (cat uni8.Blc; echo " Ni hao") | ./tromp - Ni hao +``` -A prime number sieve -==================== +```sh +$ (cat uni8.Blc; echo " Ni hao") | ./tromp +Ni hao +``` + +### A prime number sieve Even shorter than the self-interpreter is this prime number sieve in 167 bits (under 21 bytes): +``` 000100011001100101000110100 000000101100000100100010101 11110111 101001000 @@ -174,23 +213,30 @@ Even shorter than the self-interpreter is this prime number sieve in 167 bits (u 00010110 0000110110 -The n'th bit in the output indicates whether n is prime: +``` - cat primes.blc | ./tromp -b | head -c 70 - 0011010100010100010100010000010100000100010100010000010000010100000100 +The `n`th bit in the output indicates whether n is prime: -For those who prefer to digest their primes in decimal, there is oddindices.Blc, -which will print the indices of all odd characters (with lsb = 1) +```sh +$ cat primes.blc | ./tromp -b | head -c 70 +0011010100010100010100010000010100000100010100010000010000010100000100 +``` + +For those who prefer to digest their primes in decimal, there is `oddindices.Blc`, +which will print the indices of all odd characters (with +[LSB](https://en.wikipedia.org/wiki/Bit_numbering) = 1) separated by a given character: - (cat oddindices.Blc; echo -n " "; cat primes.blc | ./tromp -b) | ./tromp | head -c 70 - 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 +``` +$ (cat oddindices.Blc; echo -n " "; cat primes.blc | ./tromp -b) | ./tromp | head -c 70 +2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 +``` -A Space filling program -======================= +### A Space filling program -Program hilbert.Blc, at 143 bytes, is a very twisty "one-liner" (shown in hexadecimal): +The program `hilbert.Blc`, at 143 bytes, is a very twisty "one-liner" (shown in hexadecimal): +``` 1818181 8111154 6806041 55ff041 9d f9 de 16 ff fe 5f 3f ef f615ff9 46 84 058117e 05 @@ -206,245 +252,275 @@ Program hilbert.Blc, at 143 bytes, is a very twisty "one-liner" (shown in hexade 3fe80b2 2c18581 bfe5c10 42ff805 de ec 06 c2 c0 c0 60 8191a00167fb cbcfdf65f7c0 a20 +``` -It expects n arbitrary characters of input, and draws a space filling Hilbert curve of order n: +It expects `n` arbitrary characters of input, and draws a space filling [Hilbert +curve](https://en.wikipedia.org/wiki/Hilbert_curve) of order `n`: - (cat hilbert.Blc; echo -n "1") | ./tromp - _ - | | +```sh +$ (cat hilbert.Blc; echo -n "1") | ./tromp + _ +| | - (cat hilbert.Blc; echo -n "12") | ./tromp - _ _ - | |_| | - |_ _| - _| |_ +$ (cat hilbert.Blc; echo -n "12") | ./tromp + _ _ +| |_| | +|_ _| + _| |_ - (cat hilbert.Blc; echo -n "123") | ./tromp - _ _ _ _ - | |_| | | |_| | - |_ _| |_ _| - _| |_____| |_ - | ___ ___ | - |_| _| |_ |_| - _ |_ _| _ - | |___| |___| | +$ (cat hilbert.Blc; echo -n "123") | ./tromp + _ _ _ _ +| |_| | | |_| | +|_ _| |_ _| + _| |_____| |_ +| ___ ___ | +|_| _| |_ |_| + _ |_ _| _ +| |___| |___| | - (cat hilbert.Blc; echo -n "1234") | ./tromp - _ _ _ _ _ _ _ _ - | |_| | | |_| | | |_| | | |_| | - |_ _| |_ _| |_ _| |_ _| - _| |_____| |_ _| |_____| |_ - | ___ ___ | | ___ ___ | - |_| _| |_ |_| |_| _| |_ |_| - _ |_ _| _ _ |_ _| _ - | |___| |___| |_| |___| |___| | - |_ ___ ___ ___ ___ _| - _| |_ |_| _| |_ |_| _| |_ - | _ | _ |_ _| _ | _ | - |_| |_| | |___| |___| | |_| |_| - _ _ | ___ ___ | _ _ - | |_| | |_| _| |_ |_| | |_| | - |_ _| _ |_ _| _ |_ _| - _| |___| |___| |___| |___| |_ +$ (cat hilbert.Blc; echo -n "1234") | ./tromp + _ _ _ _ _ _ _ _ +| |_| | | |_| | | |_| | | |_| | +|_ _| |_ _| |_ _| |_ _| + _| |_____| |_ _| |_____| |_ +| ___ ___ | | ___ ___ | +|_| _| |_ |_| |_| _| |_ |_| + _ |_ _| _ _ |_ _| _ +| |___| |___| |_| |___| |___| | +|_ ___ ___ ___ ___ _| + _| |_ |_| _| |_ |_| _| |_ +| _ | _ |_ _| _ | _ | +|_| |_| | |___| |___| | |_| |_| + _ _ | ___ ___ | _ _ +| |_| | |_| _| |_ |_| | |_| | +|_ _| _ |_ _| _ |_ _| + _| |___| |___| |___| |___| |_ -A BrainFuck interpreter -======================= +``` -The smallest known BF interpreter is written in... you guessed it, BLC, +### A [Brainfuck](https://en.wikipedia.org/wiki/Brainfuck) interpreter + +The smallest known BF interpreter is written in... you guessed it, +[BLC](https://tromp.github.io/cl/Binary_lambda_calculus.html), coming in at 112 bytes (including 3 bits of padding): - od -t x4 bf.Blc - 0000000 01a15144 02d55584 223070b7 00f032ff - 0000020 7f85f9bf 956fe15e c0ee7d7f 006854e5 - 0000040 fbfd5558 fd5745e0 b6f0fbeb 07d62ff0 - 0000060 d7736fe1 c0bc14f1 1f2eff0b 17666fa1 - 0000100 2fef5be8 ff13ffcf 2034cae1 0bd0c80a - 0000120 e51fee99 6a5a7fff ff0fff1f d0049d87 - 0000140 db0500ab 3bb74023 b0c0cc28 10740e6c - 0000160 +``` +$ od -t x4 bf.Blc +0000000 01a15144 02d55584 223070b7 00f032ff +0000020 7f85f9bf 956fe15e c0ee7d7f 006854e5 +0000040 fbfd5558 fd5745e0 b6f0fbeb 07d62ff0 +0000060 d7736fe1 c0bc14f1 1f2eff0b 17666fa1 +0000100 2fef5be8 ff13ffcf 2034cae1 0bd0c80a +0000120 e51fee99 6a5a7fff ff0fff1f d0049d87 +0000140 db0500ab 3bb74023 b0c0cc28 10740e6c +0000160 +``` -It expects its input to consist of a Brainfuck program -(looking only at bits 0,1,4 to distinguish among ,-.+<>][ ) -followed by a ], followed by the input for the Brainfuck program. +It expects its input to consist of a +[Brainfuck](https://en.wikipedia.org/wiki/Brainfuck) program +(looking only at bits `0`, `1` and `4` to distinguish among `,-.+<>][ `) +followed by a `]`, followed by the input for the Brainfuck program. - more hw.bf - ++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.] - cat bf.Blc hw.bf | ./tromp - Hello World! +``` +$ more hw.bf +++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.] +$ cat bf.Blc hw.bf | ./tromp +Hello World! +``` -Curiously, the interpreter bf.Blc is the exact same size as hw.bf. +Curiously, the interpreter `bf.Blc` is the exact same size as `hw.bf`. -A BLC assembler -=============== +### A BLC assembler Writing BLC programs can be made slightly less painful with this parser that translates single-letter-variable lambda calculus into BLC: - echo "\f\x f (f (f x))" > three - cat parse.Blc three | ./tromp - 000001110011100111010 +```sh +$ echo "\f\x f (f (f x))" > three +$ cat parse.Blc three | ./tromp +000001110011100111010 -Converting between bits and bytes -================================= +``` -THe program inflate.Blc and its inverse deflate.Blc allow us to translate between -BLC and BLC8. -If you assemble a byte oriented program, you'll need to compact it into BLC8: +### Converting between bits and bytes + +The program `inflate.Blc` and its inverse `deflate.Blc` allow us to translate between +BLC and BLC8. If you assemble a byte oriented program, you'll need to compact it +into BLC8: So we could assemble an input reversing program as - echo "\a a ((\b b b) (\b \c \d \e d (b b) (\f f c e))) (\b \c c)" > reverse - cat parse.Blc reverse | ./tromp > reverse.blc +```sh +echo "\a a ((\b b b) (\b \c \d \e d (b b) (\f f c e))) (\b \c c)" > reverse +cat parse.Blc reverse | ./tromp > reverse.blc +``` and change it to BLC8 with - cat deflate.Blc reverse.blc | ./tromp > rev.Blc - wc rev.Blc - 0 1 9 rev.Blc - +``` +$ cat deflate.Blc reverse.blc | ./tromp > rev.Blc +$ wc rev.Blc + 0 1 9 rev.Blc +``` and then try it out with: - cat rev.Blc - | ./tromp - Hello, world! - ^D - !dlrow ,olleH +```sh +$ cat rev.Blc - | ./tromp +Hello, world! +^D +!dlrow ,olleH +``` -Symbolic Lambda Calculus reduction -================================== +### Symbolic Lambda Calculus reduction -BLC8 program symbolic.Blc shows individual reduction steps on symbolic lambda terms. +BLC8 program `symbolic.Blc` shows individual reduction steps on symbolic lambda terms. Here it is used to show the calculation of 2^3 in Church numerals: - echo "(\f\x f (f (f x))) (\f\x f (f x))" > threetwo - cat parse.Blc threetwo | ./tromp > threetwo.blc - cat symbolic.Blc threetwo.blc | ./tromp - (\a \b a (a (a b))) (\a \b a (a b)) - \a (\b \c b (b c)) ((\b \c b (b c)) ((\b \c b (b c)) a)) - \a \b (\c \d c (c d)) ((\c \d c (c d)) a) ((\c \d c (c d)) ((\c \d c (c d)) a) b) - \a \b (\c (\d \e d (d e)) a ((\d \e d (d e)) a c)) ((\c \d c (c d)) ((\c \d c (c d)) a) b) - \a \b (\c \d c (c d)) a ((\c \d c (c d)) a ((\c \d c (c d)) ((\c \d c (c d)) a) b)) - \a \b (\c a (a c)) ((\c \d c (c d)) a ((\c \d c (c d)) ((\c \d c (c d)) a) b)) - \a \b a (a ((\c \d c (c d)) a ((\c \d c (c d)) ((\c \d c (c d)) a) b))) - \a \b a (a ((\c a (a c)) ((\c \d c (c d)) ((\c \d c (c d)) a) b))) - \a \b a (a (a (a ((\c \d c (c d)) ((\c \d c (c d)) a) b)))) - \a \b a (a (a (a ((\c (\d \e d (d e)) a ((\d \e d (d e)) a c)) b)))) - \a \b a (a (a (a ((\c \d c (c d)) a ((\c \d c (c d)) a b))))) - \a \b a (a (a (a ((\c a (a c)) ((\c \d c (c d)) a b))))) - \a \b a (a (a (a (a (a ((\c \d c (c d)) a b)))))) - \a \b a (a (a (a (a (a ((\c a (a c)) b)))))) - \a \b a (a (a (a (a (a (a (a b))))))) +```sh +$ echo "(\f\x f (f (f x))) (\f\x f (f x))" > threetwo +$ cat parse.Blc threetwo | ./tromp > threetwo.blc +$ cat symbolic.Blc threetwo.blc | ./tromp +(\a \b a (a (a b))) (\a \b a (a b)) +\a (\b \c b (b c)) ((\b \c b (b c)) ((\b \c b (b c)) a)) +\a \b (\c \d c (c d)) ((\c \d c (c d)) a) ((\c \d c (c d)) ((\c \d c (c d)) a) b) +\a \b (\c (\d \e d (d e)) a ((\d \e d (d e)) a c)) ((\c \d c (c d)) ((\c \d c (c d)) a) b) +\a \b (\c \d c (c d)) a ((\c \d c (c d)) a ((\c \d c (c d)) ((\c \d c (c d)) a) b)) +\a \b (\c a (a c)) ((\c \d c (c d)) a ((\c \d c (c d)) ((\c \d c (c d)) a) b)) +\a \b a (a ((\c \d c (c d)) a ((\c \d c (c d)) ((\c \d c (c d)) a) b))) +\a \b a (a ((\c a (a c)) ((\c \d c (c d)) ((\c \d c (c d)) a) b))) +\a \b a (a (a (a ((\c \d c (c d)) ((\c \d c (c d)) a) b)))) +\a \b a (a (a (a ((\c (\d \e d (d e)) a ((\d \e d (d e)) a c)) b)))) +\a \b a (a (a (a ((\c \d c (c d)) a ((\c \d c (c d)) a b))))) +\a \b a (a (a (a ((\c a (a c)) ((\c \d c (c d)) a b))))) +\a \b a (a (a (a (a (a ((\c \d c (c d)) a b)))))) +\a \b a (a (a (a (a (a ((\c a (a c)) b)))))) +\a \b a (a (a (a (a (a (a (a b))))))) +``` -As expected, the resulting normal form is Church numeral 8. +As expected, the resulting normal form is [Church +numeral](https://en.wikipedia.org/wiki/Church_encoding) 8. -Taking only the first line of output gives us a sort of BLC disassembler, -an exact inverse of the above assembler. The prime number sieve disassembles as follows: +Taking only the first line of output gives us a sort of BLC disassembler, an +exact inverse of the above assembler. The prime number sieve disassembles as +follows: - cat symbolic.Blc primes.blc | ./tromp | head -1 - \a (\b b (b ((\c c c) (\c \d \e e (\f \g g) ((\f c c f ((\g g g) (\g f (g g)))) (\f \g \h \i i g (h (d f))))) (\c \d \e b (e c))))) (\b \c c (\d \e d) b) +```sh +$ cat symbolic.Blc primes.blc | ./tromp | head -1 +\a (\b b (b ((\c c c) (\c \d \e e (\f \g g) ((\f c c f ((\g g g) (\g f (g g)))) (\f \g \h \i i g (h (d f))))) (\c \d \e b (e c))))) (\b \c c (\d \e d) b) +``` Hardly any less obfuscated... The last line of - cat symbolic.Blc primes.blc | ./tromp | head -16 -starts out as - \a \b b (\c \d c) (\c c (\d \e d) (\d d (\e \f f) (\e e (\f \g g) ((\f (\g \h \i -The \a is for ignoring the rest of the input (to which the universal machine -applies the decoded lambda term). The \b b (..) (...) is the list constructor, -usually called cons, applied to a head (a list element) and a tail (another list). -In this case the element is (\c \d c), which represents the boolean true, and +```sh +cat symbolic.Blc primes.blc | ./tromp | head -16 +``` + +starts out as + +``` +\a \b b (\c \d c) (\c c (\d \e d) (\d d (\e \f f) (\e e (\f \g g) ((\f (\g \h \i +``` + +The `\a` is for ignoring the rest of the input (to which the universal machine +applies the decoded lambda term). The `\b b (..) (...)` is the list constructor, +usually called `cons`, applied to a head (a list element) and a tail (another list). +In this case the element is `(\c \d c)`, which represents the boolean true, and which we use to represent a 0 bit. This is the bit that says 0 is not prime. -The next list element (following another cons) is (\d \e d). Another 0 bit, -this time saying that 1 is not prime. The third list element is (\e \f f), +The next list element (following another `cons`) is `(\d \e d)`. Another 0 bit, +this time saying that 1 is not prime. The third list element is `(\e \f f)`, a 1 bit, confirming our suspicion that 2 is prime. As is the next number, -according to (\f \g g). We can see that the tail after the first 4 elements +according to `(\f \g g)`. We can see that the tail after the first 4 elements is still subject to further reduction. The bit for number 4 will show up -for the first time in line 30, as (\g \h g), or 0, as the result of zeroing +for the first time in line 30, as `(\g \h g)`, or 0, as the result of zeroing out all multiples of the first prime, 2. + Since my computer reaches swap hell before line 40, we can't see the next bit arriving, at least not in this symbolic reduction. -Performance -=========== +### Performance Performance is quite decent, and amazingly good for such a tiny implementation, being roughly 50% slower than a Haskell implementation of the universal machine -using so-called Higher Order Abstract Syntax which relies on the highly optimized -Haskell runtime system for evaluation. Of course individual blc programs running +using so-called [Higher Order Abstract +Syntax](https://en.wikipedia.org/wiki/Higher-order_abstract_syntax) which relies on the highly optimized +Haskell runtime system for evaluation. Of course individual BLC programs running under the interpreter perform much worse than that same program written in Haskell. Our interpreter copes well with extra levels of interpretation: - time cat primes.blc | ./tromp -b | head -c 210 > /dev/null - real 0m0.043s - time cat uni.blc primes.blc | ./tromp -b | head -c 210 > /dev/null - real 0m0.191s - time cat uni.blc uni.blc primes.blc | ./tromp -b | head -c 210 > /dev/null - real 0m1.919s - time cat uni.blc uni.blc uni.blc primes.blc | ./tromp -b | head -c 210 > /dev/null - real 0m23.514s - time cat uni.blc uni.blc uni.blc uni.blc primes.blc | ./tromp -b | head -c 210 > /dev/null - real 4m52.700s +```sh +$ time cat primes.blc | ./tromp -b | head -c 210 > /dev/null +real 0m0.043s +$ time cat uni.blc primes.blc | ./tromp -b | head -c 210 > /dev/null +real 0m0.191s +$ time cat uni.blc uni.blc primes.blc | ./tromp -b | head -c 210 > /dev/null +real 0m1.919s +$ time cat uni.blc uni.blc uni.blc primes.blc | ./tromp -b | head -c 210 > /dev/null +real 0m23.514s +$ time cat uni.blc uni.blc uni.blc uni.blc primes.blc | ./tromp -b | head -c 210 > /dev/null +real 4m52.700s +``` -Obfuscation -=========== +### Obfuscation Obfuscation is due entirely to conciseness. Some questions to ponder: -Which of the term space codes 0,1,2,3 serves multiple purposes? +Which of the term space codes `0`, `1`, `2`, `3` serve multiple purposes? Why is the environment pointer pointing into the term space? -What does the test u+m&1? do? +What does the test `u+m&1?` do? How does the program reach exit code 0? -And how do any of those blc programs work? +And how do any of those BLC programs work? -Portability -=========== +### Portability -The program freely (without casting) converts between int and int\*, causing +The program freely (without casting) converts between int and `int *`, causing many warnings; - note: expected ‘int *’ but argument is of type ‘int’ + +``` + note: expected 'int *' but argument is of type 'int' warning: assignment from incompatible pointer type warning: assignment makes integer from pointer without a cast warning: assignment makes pointer from integer without a cast - warning: incompatible implicit declaration of built-in function ‘calloc’ - warning: incompatible implicit declaration of built-in function ‘exit’ - warning: passing argument 1 of ‘d’ makes pointer from integer without a cast - warning: passing argument 1 of ‘p’ makes pointer from integer without a cast + warning: incompatible implicit declaration of built-in function 'calloc' + warning: incompatible implicit declaration of built-in function 'exit' + warning: passing argument 1 of 'd' makes pointer from integer without a cast + warning: passing argument 1 of 'p' makes pointer from integer without a cast warning: pointer/integer type mismatch in conditional expression +``` Avoiding these would make the program substantially longer, and detract from its single minded focus on conciseness. -It implicitly declares functions read, write, exit and calloc, the latter two incompatibly. -32 bit and 64 bit executables are separate Makefile targets, involving a change -from int to long and from a hardcoded sizeof of 4 to 8. +It implicitly declares functions `read()`, `write()`, `exit()` and `calloc()`, the latter two incompatibly. +32 bit and 64 bit executables are separate [Makefile](Makefile) targets, involving a change +from `int` to `long` and from a hardcoded sizeof of 4 to 8. The program has been tested to work correctly on Linux/Solaris/MacOSX both in 32 and 64 bits. -How the program works -===================== +### How the program works -See the file how13. +See the file [how.md](how.md). -Acknowledgements -================ +### Acknowledgements Christopher Hendrie, Bertram Felgenhauer, Alex Stangl, Seong-hoon Kang, -and Yusuke Endoh have contributed ideas and suggestions for improvement. +and [Yusuke Endoh](/winners.html#Yusuke_Endoh) have contributed ideas and +suggestions for improvement. -References -========== +### References -Binary Lambda Calculus +Binary Lambda Calculus - G J Chaitin, Algorithmic information theory, Volume I, Cambridge Tracts in Theoretical Computer Science, Cambridge University Press, October 1987. - + Jean-Louis Krivine. 2007. A call-by-name lambda-calculus machine diff --git a/2012/tromp/how.md b/2012/tromp/how.md new file mode 100644 index 000000000..ead070e9b --- /dev/null +++ b/2012/tromp/how.md @@ -0,0 +1,66 @@ +# Spoiler + +The program implements a so called [Krivine +machine](https://en.wikipedia.org/wiki/Krivine_machine), enhanced with a [basic +input/output system](https://en.wikipedia.org/wiki/BIOS) and a reference +counting [garbage collector](https://en.wikipedia.org/wiki/Waste_collector). The +Krivine machine is a stepwise transformer of a global state consisting of the +current term, the current environment (a list of closures), and a stack of +continuations (see the 3rd reference for details). + +The term space holds [lambda +calculus](https://en.wikipedia.org/wiki/Lambda_calculus) terms in the following +format. 0 denotes some form of IO; the only four occurrences are at: + +``` + C=13: recognizes end of a byte + C=20: recognize output of 0 bit + C=21: recognize output of 1 bit + C=end: input list, expanded lazily +``` + +`1` denotes a variable, with next entry its de [Bruijn +index](https://en.wikipedia.org/wiki/De_Bruijn_index). + +`2` denotes application with next entry the size of the term being applied. + +`3` denotes lambda abstraction. + + +A closure consists of the following items: + +0. pointer to the next closure (as part of an environment), or next record on +free list. +1. reference count +2. pointer to environment +3. lambda term (index in term space) + +Here's what each variable do: + +``` +L Lambda term space +m mode: 0 for bits and 7 for bytes +b bits remaining unread in I, -1 on EOF +D Desirable temporary +c continuation context +a active environment pointer +C Current term index +U Ultimate term pointer +u utility entry +B Born to be free-list of closures +I Input character +O Output character +e entry of current term +``` + +Here's what each of the 6 auxiliary functions do: + +``` +s variable lookup in active environment with de Bruijn index u +S gets one bit of input, setting b to -1 on EOF or to remaining number of bits in current byte +k copy fragment from string literal holding lambda terms xor 46 into current end of term space +x expand input, adding 11 (resp. 99) entries to term space for bit (resp. byte) mode +p parses BLC-encoded lambda term using S(), stores results in term space and returns length +d decrease reference counter, add record to free list on reaching zero +``` + diff --git a/2012/tromp/how13 b/2012/tromp/how13 deleted file mode 100644 index 1c5989993..000000000 --- a/2012/tromp/how13 +++ /dev/null @@ -1,45 +0,0 @@ -Gur cebtenz vzcyrzragf n fb pnyyrq Xevivar znpuvar, -raunaprq jvgu n onfvp vachg/bhgchg flfgrz -naq n ersrerapr pbhagvat tneontr pbyyrpgbe. -Gur Xevivar znpuvar vf n fgrcjvfr genafsbezre bs n tybony fgngr pbafvfgvat bs -gur pheerag grez, gur pheerag raivebazrag (n yvfg bs pybfherf), naq n fgnpx bs pbagvahngvbaf -(Frr gur 3eq ersrerapr sbe qrgnvyf.) - -Gur grez fcnpr ubyqf ynzoqn pnyphyhf grezf va gur sbyybjvat sbezng -0 qrabgrf fbzr sbez bs VB; gur bayl sbhe bpphenaprf ner ng - P=13: erpbtavmrf raq bs n olgr - P=20: erpbtavmr bhgchg bs 0 ovg - P=21: erpbtavmr bhgchg bs 1 ovg - P=raq: vachg yvfg, rkcnaqrq ynmvyl -1 qrabgrf n inevnoyr, jvgu arkg ragel vgf qr Oehvwa vaqrk -2 qrabgrf nccyvpngvba jvgu arkg ragel gur fvmr bs gur grez orvat nccyvrq -3 qrabgrf ynzoqn nofgenpgvba - -N pybfher pbafvfgf bs gur sbyybjvat vgrzf -0 cbvagre gb gur arkg pybfher (nf cneg bs na raivebazrag), be arkg erpbeq ba serr yvfg -1 ersrerapr pbhag -2 cbvagre gb raivebazrag -3 ynzoqn grez (vaqrk va grez fcnpr) - -Urer'f jung rnpu inevnoyr qbrf: -Y Ynzoqn grez fcnpr -z zbqr; 0 sbe ovgf naq 7 sbe olgrf -o ovgf erznvavat haernq va V, -1 ba RBS -Q Qrfvenoyr grzcbenel -p pbagvahngvba pbagrkg -n npgvir raivebazrag cbvagre -P Pheerag grez vaqrk -H Hygvzngr grez cbvagre -h hgvyvgl ragel -O Obea gb or serr-yvfg bs pybfherf -V Vachg punenpgre -B Bhgchg punenpgre -r ragel bs pheerag grez - -Urer'f jung rnpu bs gur 6 nhkvyvnel shapgvbaf qbrf: -f: inevnoyr ybbxhc va npgvir raivebazrag jvgu qr Oehvwa vaqrk h -F: trgf bar ovg bs vachg, frggvat o gb -1 ba RBS be gb erznvavat ahzore bs ovgf va pheerag olgr -x: xbcl sentzrag sebz fgevat yvgreny ubyqvat ynzoqn grezf kbe 46 vagb pheerag raq bs grez fcnpr -k: kcnaq vachg, nqqvat 11 (erfc. 99) ragevrf gb grez fcnpr sbe ovg (erfc. olgr) zbqr -c: cnefrf oyp-rapbqrq ynzoqn grez hfvat F(), fgberf erfhygf va grez fcnpr naq ergheaf yratgu -q: qrpernfr ersrerapr pbhagre, nqq erpbeq gb serr yvfg ba ernpuvat mreb diff --git a/2012/vik/.gitignore b/2012/vik/.gitignore index a9f44da13..4e1643ecb 100644 --- a/2012/vik/.gitignore +++ b/2012/vik/.gitignore @@ -5,3 +5,4 @@ restored-chocolate.png restored-ioccc.png restored.png vik +vik.alt diff --git a/2012/vik/Makefile b/2012/vik/Makefile index aee877aa6..fe3b8bfba 100644 --- a/2012/vik/Makefile +++ b/2012/vik/Makefile @@ -112,8 +112,8 @@ OBJ= ${PROG}.o DATA= chocolate.png ioccc.png TARGET= ${PROG} # -ALT_OBJ= -ALT_TARGET= +ALT_OBJ= ${PROG}.alt.o +ALT_TARGET= ${PROG}.alt ################# diff --git a/2012/vik/README.md b/2012/vik/README.md index 05345933e..4efa10f73 100644 --- a/2012/vik/README.md +++ b/2012/vik/README.md @@ -1,8 +1,8 @@ # Best use of cocoa - Bronze award - Daniel Vik - - +Daniel Vik + + ## To build: @@ -10,7 +10,8 @@ make ``` -This entry requires [Zlib](http://www.zlib.net/). +This entry requires [Zlib](https://www.zlib.net). + ## To run: @@ -44,6 +45,16 @@ To extract the embedded PNG: ./vik d encodedimg.png > restored.png ``` +There is an alternate version which might work for Windows. See 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 to the +program or if invalid arguments or images of mismatching sizes or unsupported +pixel formats though we note that your computer might also [halt and catch +fire](https://en.wikipedia.org/wiki/Halt_and_Catch_Fire_(computing)) :-) + ## Try: ```sh @@ -53,45 +64,65 @@ To extract the embedded PNG: ./vik d ioccc-in-chocolate.png > restored-ioccc.png ``` +### Alternate code: + +Based on the author's description it should be able to get this entry to work +for Windows. With his instructions [Cody Boone +Ferguson](/winners.html#Cody_Boone_Ferguson) added the alternate version that +does this for the few who might use Windows. To compile: + +```sh +make alt +``` + +Use `vik.alt` as you would `vik` above. + +We're not sure whether we want to thank Cody or not for this :-) and he's not +sure if he wants to be thanked either :-) but we appreciate it nonetheless. + ## Judges' remarks: References to chocolate had no effect on judging this entry. We guarantee it. -Can you discern hidden pieces of chocolate in `chocolate-in-ioccc.png`? +Can you discern hidden pieces of chocolate in +[chocolate-in-ioccc.png](chocolate-in-ioccc.png)? + +![chocolate in ioccc](chocolate-in-ioccc.png "Chocolate in IOCCC") ## Author's remarks: ### Introduction -This program is a steganography application for embedding an image or text -into another image as well as extracting the embedded image or text back. -The program stores the embedded image or text in the low bits of the RGB -values. +This program is a [steganography](https://en.wikipedia.org/wiki/Steganography) +application for embedding an image or text into another image as well as +extracting the embedded image or text back. The program stores the embedded +image or text in the low bits of the RGB values. -The program supports any 8 bit true color PNG images (RGB, RGBA, grayscale, -and grayscale+alpha). The output image is always 8 bit RGB. When embedding +The program supports any 8 bit true color PNG images (RGB, RGBA, greyscale, +and greyscale+alpha). The output image is always 8 bit RGB. When embedding one image into another, the width and height needs to be the same. -The program only updates the IDAT and IHDR chunks of the source image. Any +The program only updates the `IDAT` and `IHDR` chunks of the source image. Any additional chunks are copied into the resulting image. ### Bonus Extractor: -For some reason the chocolate image seems to have some special properties. -Apart from being quite big and a little bit noisy, it appears that when -embedded into another image and extracted, the bitmap data is also a valid -brain$#@$ program. It is of course possible to get the bitmap data from the -extracted image, and run it through any of the previous winning brain$#@$ -interpreters, but I thought it would be easier to include an interpreter in -the program to avoid the hassle: +For some reason the chocolate image seems to have some special properties. +Apart from being quite big and a little bit noisy, it appears that when embedded +into another image and extracted, the bitmap data is also a valid +[brain$#@$](https://en.wikipedia.org/wiki/Brainfuck) program. It is of course +possible to get the bitmap data from the extracted image, and run it through any +of the previous winning brain$#@$ interpreters, but I thought it would be easier +to include an interpreter in the program to avoid the hassle: ```sh ./vik e ioccc.png chocolate.png > encodedimg.png ./vik b encodedimg.png ``` -It is of course also possible to embed a brain$#@$ program as a text file +It is of course also possible to embed a +[brain$#@$](https://en.wikipedia.org/wiki/Brainfuck) program as a text file (as explained above) and decode it, e.g.: ```sh @@ -101,26 +132,25 @@ It is of course also possible to embed a brain$#@$ program as a text file ### Obfuscation -I really wanted to keep the program simple, so instead of adding multiple -macros or helper methods that can be confusing, I placed all functionality -in the main function. Main is called recursively and quite extensively, but -it gives the benefit that all invocations of the function has the same -parameters, argv and argc. This really helps readability, as a programmer -doesn't need to remember several variable or function names. I also tried -to reduce the number of keywords, and the program only has four for-loops -followed by a single return statement. There is a little bit of use of the -question mark operator, but this is really there to keep the program as -simple as possible. +I really wanted to keep the program simple, so instead of adding multiple macros +or helper methods that can be confusing, I placed all functionality in the +`main()` function. `main()` is called recursively and quite extensively, but it +gives the benefit that all invocations of the function have the same parameters, +`argv` and `argc`. This really helps readability, as a programmer doesn't need +to remember several variable or function names. I also tried to reduce the +number of keywords, and the program only has four for-loops followed by a single +return statement. There is a little bit of use of the ternary (`?:`) operator, +but this is really there to keep the program as simple as possible. ### Portability -The program is portable to most platforms that have zlib available. The -only system dependency is that the program relies on writing binary data to -stdout. +The program is portable to most platforms that have [zlib](https://www.zlib.net) +available. The only system dependency is that the program relies on writing +binary data to stdout. -By default, Microsoft compilers adds carriage returns to new lines, and to +By default, Microsoft compilers adds carriage returns to new lines, and to compile the program on this platform, the following line can be added after -the variable declarations in the main declaration in order to run +the variable declarations in the main declaration in order to run correctly: ```c @@ -129,31 +159,33 @@ _setmode(_fileno(stdout), 0x8000); ### Limitations -The program doesn’t have many error checks so passing in invalid arguments +The program doesn't have many error checks so passing in invalid arguments or images of mismatching sizes, or unsupported pixel formats will cause the program to crash. ### Extendability -Since a lot of care was taken to keep the code simple, it turned out to be -quite easy to extend functionality. I did include a small brain$#@$ after I +Since a lot of care was taken to keep the code simple, it turned out to be +quite easy to extend functionality. I did include a small +[brain$#@$](https://en.wikipedia.org/wiki/Brainfuck) after I realized that the chocolate image had some interesting properties. -But there is more functionality I added that didn’t fit within the size -limits and could not remain included. For example, I added a method to -format source code based on a PNG image. So the format of the program is +But there is more functionality I added that didn't fit within the size +limits and could not remain included. For example, I added a method to +format source code based on a PNG image. So the format of the program is actually done by the program itself. -And to be honest, the chocolate image did not have a brain$#@$ program -embedded to begin with. I added functionality to the program to embed a -brain$#@$ into a PNG image and used it to create the image provided with +And to be honest, the chocolate image did not have a +[brain$#@$](https://en.wikipedia.org/wiki/Brainfuck) program +embedded to begin with. I added functionality to the program to embed a +brain$#@$ into a PNG image and used it to create the image provided with the entry. -I also added a method to analyze PNG images, to print the size and format, +I also added a method to analyze PNG images, to print the size and format, as well as the scan line filters. -All these features were quite easy to add, much thanks to the (actually +All these features were quite easy to add, much thanks to the (actually pretty good) design of the code. ## Copyright and CC BY-SA 4.0 License: diff --git a/2012/vik/vik.alt.c b/2012/vik/vik.alt.c new file mode 100644 index 000000000..04145bb39 --- /dev/null +++ b/2012/vik/vik.alt.c @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include "zlib.h" + + + + + int + i,j,k,l + ,m,n,Q,W,H, + B,Z,Y,X,O=1<<24 + ; char*A[999],x[ + 1<<24],z[1<<24], + s[1<<24],t[2<<24 + ],w[2<<24],*E; + uLong N; FILE + *f ; int main( + int c,char**v){ + unsigned char**V + =(unsigned char + **)v;_setmode( + _fileno(stdout), + 0x8000); for(m=0; + c==-11&&m0?X:-X,Y=i- + Z,Y=Y>0?Y:-Y,Z=i+j + -Z-Z,Z=Z>0?Z:-Z,X>Y + ||X>Z?Y >Z?k:j:i): + (i+j) /2:j:i:0)); + for( E=t+O; *v-1[v] + &&c== -16; ++*v)n=**v,n + -62? n-60?n -91?n-93||! + m|| !*E?* v:(*v=A[--m+9 + ]): (A[9+ m++]=*v-1):--E + :++ E ,n-43?n-44?n-45? + n- 46 ?0:putchar(*E):--*E + :(* E= getchar()):++*E; for(; + 7< -c &&11>-c&&*v!=5[v]; ++*v) + **V =c +8?c+9?*V[1]++<<6|56:**V|~3 + &*V [1] ++:**V>>6; for(; m>m + %8) :(* V[1]++=V[0][m/8]<0 ?n=main(-7,(Q=**++v,N=0x49444154,*A + =s+4, main (-128 ,A),A[1]=*++v,A [4]=z,*A=x,A)) + ,c=A[ 6] -x- 12,Q-101?main(-19,(main(-10,(A[5]= + t+n, *A= t, A[1]=z,A)),*A=t,A [1]=w,A)):main(-9,( + main( -8 ,((n=main(-7,(A[1] =*++v,A[4]=t,*A=s+4, + A)))<0 ? main (-18,(n= -n,*A=s,A[1]=t,A)):0,A[ + 5]=t+n ,*A= t,A) ),*A=t, A[1]=z,A)),98-Q?E=memcmp( + w,s,4 )? n+= main(-22 ,(*A=z,A[1 ]=t,A[2]=t+n + ,A)), N=n= main (-23,(*A=t, A[1]=z,A[2 ]=z+n,A)), + memmove (x+ c+n+12 ,x+c,12),memcpy(x+c+8,t, n),main(-128 + ,(*A= x+c +4,A)) ,N=crc32( 0,memcpy(x +c+4,s,4),n + +4), main (-128, (*A=x+c+ n+12,A)),n +=c+24,x:(n= + strlen (w +4),w+4),fwrite(E ,1,n,stdout): main(-16,(*A=w, + A[1]=w +H, A)) :-c>31?main(c+=32 ,(*--*v=N,N>>=8,v)):-++c<4?(-c) + [*V]+256*main(c,v ):c+23?c+22?c+21?c+6?c+5?c+4?0:(N=O,uncompress(*v=s+4,&N + ,v[3],v[2]-v[3] ),main(c-7,v),H):(n-=l=main(-4,v)+12,5[*v]-68?(v[6]=(*v+= + l)):(memcpy(v[2],*v+8,l-12),v[2]+=l-12,memmove(*v,*v+l,n)),main(c-(n>8),v)) + :(n= main(-24,v),main(-4,v)-0x89504e47?-H:main(c,(*v+=16,W=main(-4,v)*3,*v + += 4,H=main(-4,v)*W,B=(*v)[5],(*v)[5]=2,N=crc32(0,*v- 8,17),*v+= + 13 ,main(-128,v),v[3]=v[2]=w+O,*v-=21,v))):(* *v=0,memcpy + (++*v ,v[1],W),*v+=W,v[1]+=W, 1+main((v[1] + !=v[2]) *--c,v)):(N=O + ,compress(*v,&N, v[1],v[2]-v[1]),N):(f= + fopen(v[1],"rb"))?fclose((n=fread(*v,1,O,f),f)), + n[*v]=0,n:(strcpy(*v,v[1]),0); } diff --git a/2012/zeitak/README.md b/2012/zeitak/README.md index 5afa0331c..b44c8ba3b 100644 --- a/2012/zeitak/README.md +++ b/2012/zeitak/README.md @@ -15,8 +15,8 @@ make ./zeitak < file.c ``` -where file.c is the file to be checked for nesting errors. For example, you may -try incorrect.c and the program itself. +where `file.c` is the file to be checked for nesting errors. For example, you may +try [incorrect.c](incorrect.c) and the program itself. ## Try: @@ -25,10 +25,13 @@ try incorrect.c and the program itself. ./zeitak < incorrect.c ``` +NOTE: it prints an error and exits on the first nesting error so it will not +detect multiple issues! + ### Alternate code -An alternate version of this entry, `zeitak.alt.c`, is provided. -The file `zeitak.alt.c` provides a version that has been slightly +An alternate version of this entry, [zeitak.alt.c](zeitak.alt.c), is provided. +The file [zeitak.alt.c](zeitak.alt.c) provides a version that has been slightly deobfuscated. You may find reading that file helpful in your attempt to understand this extremely subtle entry. @@ -40,13 +43,14 @@ make alt Use `zeitak.alt` as you would `zeitak` above. -## Judges' remarks +## Judges' remarks: This is an extremely subtle and twisted piece of Gold award winning code! The judges had spent a considerable amount of time analyzing this entry. At one point we spent -[18 minutes](https://twitter.com/ioccc/status/252162898800033792) +[18 +minutes](https://web.archive.org/web/20130925190722/https://twitter.com/ioccc/status/252162898800033792) just to understand 18 key characters of this code. ## Author's remarks @@ -58,8 +62,8 @@ just to understand 18 key characters of this code. As you have probably understood by looking at the source\*, this program has something to do with parenthesis (and equality of opening and closing parenthesis, if you look close enough). It goes over the file given to it and -checks that every opening (, [, or { has a matching closing one and -vice versa. It also checks that every " or ' is closed. +checks that every opening `(`, `[`, or `{` has a matching closing one and +vice versa. It also checks that every `"` or `'` is closed. If an error is detected, an error message will be printed. If the problem is a superfluous closing bracket, it will even print a few characters @@ -74,51 +78,50 @@ around it's position. printf(")"); -* Doesn't get confused by the 1984/anonymous entry! +* Doesn't get confused by the [1984/anonymous](/1984/anonymous/anonymous.c) entry! #### Mis-Features -* Escapes (e.g. `\"`) are ignored, so the following line will produce - an error: +* Escapes (e.g. `\"`) are ignored, so the following line will produce + an error: printf("\""); #### Obfuscation -IOCCC winners already contain entries without digits, control-flow +[IOCCC winners](/years.html) already contain entries without digits, control-flow keywords and certain operators in their source. This entry has an even more limited source, that is: -* Without any digits. -* Without any character constants. -* Without using functions from headers other than stdio. -* Without any control-flow keywords (not even the ?: operator). -* Without any arithmetic or logic operators! +* Without any digits. +* Without any character constants. +* Without using functions from headers other than stdio. +* Without any control-flow keywords (not even the `?:` operator). +* Without any arithmetic or logic operators! So, what's left? Parenthesis, and lots of them, as looking at the source will reveal immediately. The main obfuscation is building the whole algorithm using only function calls, typecasts, array lookups and pointer operators. -Additional obfuscations include: +##### Additional obfuscations include: -* Extensive reuse of identifiers: Macros share names with variables, inner - curly braces scopes contain variables with names identical to those in the - outer scopes and some of the variables have different uses in different - parts of the program. Even the large array has more than one use. -* A complicated data structure with "unused" fields. -* Mostly one-letter identifiers. -* Complex recursion: A function might call itself once, twice, or not at all. +* Extensive reuse of identifiers: Macros share names with variables, inner + curly braces scopes contain variables with names identical to those in the + outer scopes and some of the variables have different uses in different + parts of the program. Even the large array has more than one use. +* A complicated data structure with "unused" fields. +* Mostly one-letter identifiers. +* Complex recursion: A function might call itself once, twice, or not at all. -#### Compilation/Running Notes +#### Compilation/Portability/Running Notes -* The program requires `char` to be one byte and pointers to be - at least two bytes long. +* The program requires `char` to be one byte and pointers to be + at least two bytes long. -* The program was tested on the following platforms: - -** Ubuntu 9.04 32-bit with GCC -** Windows 7 32-bit with GCC -** Windows 7 32-bit with OpenWatcom +* The program was tested on the following platforms: + - Ubuntu 9.04 32-bit with GCC + - Windows 7 32-bit with GCC + - Windows 7 32-bit with OpenWatcom ## Copyright and CC BY-SA 4.0 License: diff --git a/2013/birken/.gitignore b/2013/birken/.gitignore index e5a552e19..88dd6a63b 100644 --- a/2013/birken/.gitignore +++ b/2013/birken/.gitignore @@ -1 +1,2 @@ birken +birken.alt diff --git a/2013/birken/Makefile b/2013/birken/Makefile index 7afa1bc6f..976736cc7 100644 --- a/2013/birken/Makefile +++ b/2013/birken/Makefile @@ -57,7 +57,7 @@ ARCH= # Defines that are needed to compile # -CDEFINE= +CDEFINE= -DZ=15000 # Include files that are needed to compile # @@ -120,8 +120,8 @@ DATA= belmont.txt bloober.txt bomberman.txt boo.txt bub.txt cheepcheep.txt \ toad.txt triple0.gif triple1.gif TARGET= ${PROG} # -ALT_OBJ= -ALT_TARGET= +ALT_OBJ= ${PROG}.alt.o +ALT_TARGET= ${PROG}.alt ################# @@ -138,6 +138,8 @@ all: data ${TARGET} ${PROG}: ${PROG}.c ${CC} ${CFLAGS} $< -o $@ ${LIBS} +${PROG}.alt: ${PROG}.alt.c + ${CC} ${CFLAGS} $< -o $@ ${LIBS} # alternative executable # alt: data ${ALT_TARGET} diff --git a/2013/birken/README.md b/2013/birken/README.md index f50a40eee..8fffd02db 100644 --- a/2013/birken/README.md +++ b/2013/birken/README.md @@ -1,8 +1,8 @@ # Best painting tool - Michael Birken - - +Michael Birken + + ## To build: @@ -10,46 +10,109 @@ make ``` +An alternate version which allows one to more easily see what is going on is +available. See Alternate code section below for more details. + +WARNING: if you have a problem with flashing colours please consider whether you +should try this entry or not. This problem can also occur with the alternate +version but to a lesser degree depending on how it's configured. + ## To run: ```sh ./birken < 17_columns_wide_paint_by_numbers_file ``` + ## Try: ```sh ./birken < ioccc.txt perl -e 'map{map{print int(rand()*8);}(0..16);print chr(10);}(0..30);' | tr '[0-4]' ' '| ./birken + +./demo.sh + +BIRKEN=birken.alt ./demo.sh ``` +### Alternate code: + +Along with the [demo.sh](demo.sh), based on the author's recommendations, +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) added an alternate +version for this entry which allows one to control how fast the painting is +done. To compile: + + +```sh +make clobber alt +``` + +Finding the 'right' default value was a fine line; the default, 15000 +microseconds (0.015 seconds), will take quite a while to finish but it allows +one to more easily see what is going on. Even easier to see would be 25000 but +these values make it quite slow and one could easily lose interest. Like some +other entries where Cody made this type of alternate version he made it +configurable at compile time. If you wish to speed it up by 100% you can instead +do: + + +```sh +make clobber CDEFINE=-DZ=7500 alt +``` + +That will speed it up a fair amount but of course it will still take a while to +finish. If you wish to speed it up 200% you can use instead `3750`. Doing this +you might find the right value; use ctrl-c to terminate the program early. + +Given that the [original](birken.c) version is easy to see without a delay this +slower value shouldn't be a problem. + +Use `birken.alt` as you would `birken` above. + +Thank you Cody! + + ## Judges' remarks: This program also wins the "Most amusing abuse of the iocccsize tool" award; although not the -absolute best: it is possible to achieve 0 by writing +absolute best: it is possible to achieve 0 by writing: +```c /* *\ /.... +``` -The game of Tetris had been used in many endeavors, from studying [algorithmic complexity](http://arxiv.org/abs/cs/0210020) to [treating PTSD](http://www.livescience.com/19894-tetris-treat-ptsd-flashbacks.html). +The game of Tetris had been used in many endeavors, from studying [algorithmic +complexity](http://arxiv.org/abs/cs/0210020) to [treating +PTSD](http://www.livescience.com/19894-tetris-treat-ptsd-flashbacks.html) and +it's even been [put on MIT's Green +Building](http://hacks.mit.edu/Hacks/by_year/2012/tetris/). Using it for painting by numbers looks like a novel idea. ## Author's remarks: ### About This Document -This document is best viewed as an HTML file in a browser that supports animated gifs. +This document is best viewed as an HTML file in a browser that supports animated +[GIF](https://en.wikipedia.org/wiki/GIF)s. See the files: `*.txt`, `*.png` and `*.gif`. ### Abstract -By rotating, positioning and dropping a predetermined sequence of pieces, this program exploits the mechanics of Tetris to generate arbitrary images. +By rotating, positioning and dropping a predetermined sequence of pieces, this +program exploits the mechanics of Tetris to generate arbitrary images. ### Algorithm Overview -The algorithm converts pixels from a source image into squares in the Tetris playfield, one row at a time from the bottom up. To generate an individual square, the algorithm assembles a structure consisting of a rectangular region fully supported by a single square protruding from the bottom. When the rectangular region is completed, its rows are cleared, leaving behind the protruding square. Three examples of the process appear below. +The algorithm converts pixels from a source image into squares in the +[Tetris](https://en.wikipedia.org/wiki/Tetris) play-field, one row at a time +from the bottom up. To generate an individual square, the algorithm assembles a +structure consisting of a rectangular region fully supported by a single square +protruding from the bottom. When the rectangular region is completed, its rows +are cleared, leaving behind the protruding square. Three examples of the process +appear below. ![](pen0.gif) @@ -57,41 +120,89 @@ The algorithm converts pixels from a source image into squares in the Tetris pla ![](pen2.gif) -During construction of a row, all of the squares produced by this method must be supported. In the images above, the generated squares are supported by the floor of the playfield. However, if an arbitrary row contains holes, it may not provide the support necessary for the construction of the row above it. The algorithm solves this problem by constructing a flat platform on top of the row with holes. In the animation below, a platform is built above a row comprising of a single red square. The platform is a temporary structure and inserting the final piece removes it. +During construction of a row, all of the squares produced by this method must be +supported. In the images above, the generated squares are supported by the floor +of the play-field. However, if an arbitrary row contains holes, it may not +provide the support necessary for the construction of the row above it. The +algorithm solves this problem by constructing a flat platform on top of the row +with holes. In the animation below, a platform is built above a row comprising +of a single red square. The platform is a temporary structure and inserting the +final piece removes it. ![](platform0.gif) -Below, a row containing 5 red squares is deposited above a row containing 3 red squares. This is accomplished by building a flat platform on top of the lower row. The platform provides the support necessary to generate the 5 red squares. Finally, the platform is removed by inserting its final piece and the new row drops into place. Note, if the algorithm needed to generate the rows in the opposite order (a row of 3 red squares above a row of 5 red squares), a platform would not be necessary. +Below, a row containing 5 red squares is deposited above a row containing 3 red +squares. This is accomplished by building a flat platform on top of the lower +row. The platform provides the support necessary to generate the 5 red squares. +Finally, the platform is removed by inserting its final piece and the new row +drops into place. Note, if the algorithm needed to generate the rows in the +opposite order (a row of 3 red squares above a row of 5 red squares), a platform +would not be necessary. ![](platform1.gif) ### Single Square Emitters -For reference, the names of the 7 Tetriminos (the game pieces) appear in the table below. +For reference, the names of the 7 +[tetriminos](https://en.wikipedia.org/wiki/Tetromino) (the game pieces or +actually a kind of geometric shape used in +[Tetris](https://en.wikipedia.org/wiki/Tetris)) appear in the table below. ![](names.png) -This algorithm was tailored specifically to render sprites from early video games. Those games packed graphics into 8×8 tiles where 2 bits were dedicated to each pixel. Consequentially, sprites usually contained only 3 colors plus transparent regions and they were typically sized either 16×16 or 16×32 pixels. +This algorithm was tailored specifically to render sprites from early video +games. Those games packed graphics into 8x8 tiles where 2 bits were dedicated to +each pixel. Consequentially, sprites usually contained only 3 colors plus +transparent regions and they were typically sized either 16x16 or 16x32 pixels. -The animation below depicts all the patterns used to emit single squares. J, T and L Tetriminos are used interchangeably within each pattern to produce the protruding square at the bottom. The algorithm assigns those Tetriminos to the 3 colors present in the sprite. The remaining Tetriminos are assigned arbitrary colors. And, all the colors remain constant during gameplay. +The animation below depicts all the patterns used to emit single squares. `J`, +`T` and `L` [tetriminos](https://en.wikipedia.org/wiki/Tetromino) are used +interchangeably within each pattern to produce the protruding square at the +bottom. The algorithm assigns those tetriminos to the 3 colors present in the +sprite. The remaining tetriminos are assigned arbitrary colors. And, all the +colors remain constant during gameplay. ![](pen4.gif) -It is not possible to emit a square of all 3 colors in the first 2 and the last 2 columns due to the shapes of the 3 Tetriminos. As a result, the minimal width of a playfield to accommodate a 16 pixel wide sprite is 2 + 16 + 2 = 20 squares. However, it turns out that 20 is too small. +It is not possible to emit a square of all 3 colors in the first 2 and the last +2 columns due to the shapes of the 3 +[tetriminos](https://en.wikipedia.org/wiki/Tetromino). As a result, the minimal +width of a play-field to accommodate a 16 pixel wide sprite is `2 + 16 + 2 = 20` +squares. However, it turns out that 20 is too small. -As illustrated below, the region above the protruding square cannot exclusively consist of a single row because the only pieces that could fit, the I Tetriminos, are unsupported. +As illustrated below, the region above the protruding square cannot exclusively +consist of a single row because the only pieces that could fit, the `I` +[tetriminos](https://en.wikipedia.org/wiki/Tetromino), are unsupported. ![](pen5.gif) -With 2 rows, the only means of spanning the full playfield width in a way that remains supported is to use S and Z Tetriminos. But, that will always leave holes in the upper row. +With 2 rows, the only means of spanning the full play-field width in a way that +remains supported is to use `S` and `Z` +[tetriminos](https://en.wikipedia.org/wiki/Tetromino). But, that will always +leave holes in the upper row. ![](pen6.gif) -The minimal number of rows required above the protruding square is 3 and as shown repeatedly above, such patterns do exist. 20 squares is the minimal width required to fit a 16 pixel wide sprite. But, 20 × 3 + 1 = 61, which is not divisible by 4 and hence not constructible out of Tetriminos. However, a width of 21 yields 21 × 3 + 1 = 64, which can be built with 16 Tetriminos. That width actually enables the algorithm to render sprites up to 17 pixels wide. +The minimal number of rows required above the protruding square is 3 and as +shown repeatedly above, such patterns do exist. 20 squares is the minimal width +required to fit a 16 pixel wide sprite. But, `20 * 3 + 1 = 61`, which is not +divisible by 4 and hence not constructible out of +[tetriminos](https://en.wikipedia.org/wiki/Tetromino). However, a width of 21 +yields `21 * 3 + 1 = 64`, which can be built with 16 tetriminos. That width +actually enables the algorithm to render sprites up to 17 pixels wide. -The original Tetris playfield is 10×20 squares, a 1:2 ratio. The program maintains that ratio by using a playfield of 21×42 squares. +The original [Tetris](https://en.wikipedia.org/wiki/Tetris) play-field is 10 x +20 squares, a 1:2 ratio. The program maintains that ratio by using a play-field +of 21 x 42 squares. -Since J, T and L Tetriminos are used interchangeably to produce the emitted square and 3 squares of those Tetriminos contribute to the row above it, there are 21 − 3 + 1 = 19 single square emitting patterns. However, due to mirror symmetry, there are really only 10 patterns. Clearing 3 rows works for the majority of them. But, an exhaustive computer search revealed that 2 of the patterns require more. The next possible option is 7 rows since 21 × 7 + 1 = 148, requiring 37 Tetriminos. As the images below show, those patterns do exist. +Since `J`, `T` and `L` [tetriminos](https://en.wikipedia.org/wiki/Tetromino) are +used interchangeably to produce the emitted square and 3 squares of those +tetriminos contribute to the row above it, there are `21 - 3 + 1 = 19` single +square emitting patterns. However, due to mirror symmetry, there are really +only 10 patterns. Clearing 3 rows works for the majority of them. But, an +exhaustive computer search revealed that 2 of the patterns require more. The +next possible option is 7 rows since `21 * 7 + 1 = 148`, requiring 37 +tetriminos. As the images below show, those patterns do exist. ![](pen7.gif) @@ -99,45 +210,83 @@ Since J, T and L Tetriminos are used interchangeably to produce the emitted squa ### Platforms -Before a row is constructed, the algorithm inspects the row below it. If the row below fails to provide support for all of the squares to be deposited above it, then a temporary platform is required. When that platform is removed, the new row will drop, leaving some of the squares apparently floating above empty space due to the way that gravity works in the original Tetris. +Before a row is constructed, the algorithm inspects the row below it. If the +row below fails to provide support for all of the squares to be deposited above +it, then a temporary platform is required. When that platform is removed, the +new row will drop, leaving some of the squares apparently floating above empty +space due to the way that gravity works in the original +[Tetris](https://en.wikipedia.org/wiki/Tetris). -The illustration below depicts the 10 platform patterns (really only 5 considering mirror symmetry). The construction of a platform begins by dropping a T Tetrimino on top one of the squares of the last generated row. The remaining Tetriminos support each other down to that first T. Meaning, as long as the previously generated row contains at least 1 square, like the red square below, then it is possible to construct a flat platform above it for the generation of the next row. +The illustration below depicts the 10 platform patterns (really only 5 +considering mirror symmetry). The construction of a platform begins by dropping +a `T` [tetrimino](https://en.wikipedia.org/wiki/Tetromino) on top one of the +squares of the last generated row. The remaining tetriminos support each other +down to that first `T`. Meaning, as long as the previously generated row +contains at least 1 square, like the red square below, then it is possible to +construct a flat platform above it for the generation of the next row. ![](platform2.gif) -In the middle of platform construction, the bottom row gets completed and cleared, leaving 3 rows above it. The final J or L Tetrimino that will remove those rows is not inserted until the square emitters are done generating the next row of the sprite on top of the platform. That final piece precludes square emission in the first and last 2 columns. But, as discussed above, the square emitters are limited to the 17 inner columns due to the geometry of the J, T and L Tetriminos used in the process. +In the middle of platform construction, the bottom row gets completed and +cleared, leaving 3 rows above it. The final `J` or `L` +[tetrimino](https://en.wikipedia.org/wiki/Tetromino) that will remove those rows +is not inserted until the square emitters are done generating the next row of +the sprite on top of the platform. That final piece precludes square emission +in the first and last 2 columns. But, as discussed above, the square emitters +are limited to the 17 inner columns due to the geometry of the `J`, `T` and `L` +tetriminos used in the process. -Also, of the 19 possible ways to start constructing a platform on top of a T Tetrimino, only the 10 patterns shown above exist. +Also, of the 19 possible ways to start constructing a platform on top of a `T` +[tetrimino](https://en.wikipedia.org/wiki/Tetromino), only the 10 patterns shown +above exist. ### Program Input -The input sprite is represented textually. Digit characters `0` to `7` correspond to pixels with colors from the palette below. +The input sprite is represented textually. Digit characters `0` to `7` +correspond to pixels with colors from the palette below. ![ANSI color palette](palette.png) -As discussed above, sprites are limited to a maximum of 3 colors from this palette. +As discussed above, sprites are limited to a maximum of 3 colors from this +palette. All other characters are interpreted as transparent pixels. -The maximum permissible size of the input text is 32 rows by 17 columns. Row length can vary as long as no single row exceeds 17 characters. +The maximum permissible size of the input text is 32 rows by 17 columns. Row +length can vary as long as no single row exceeds 17 characters. Every row must contain at least one palette digit character. -The `examples` directory contains several sprites in this textual format that can be fed into standard input. Several examples take advantage of the Tetris playfield background color. Instead of using character `0`, internal regions marked as transparent are effectively rendered as black. +The `*.txt` files contain different sprites in this textual format that can be +fed into standard input. Several examples take advantage of the +[Tetris](https://en.wikipedia.org/wiki/Tetris) play-field background color. +Instead of using character `0`, internal regions marked as transparent are +effectively rendered as black. -###Program Output +### Program Output -The program conceptually uses Tetris as an output device similar to a line printer. It restricts itself to those operations that can be performed on the Tetris playfield: spawning, rotating, positioning and dropping Tetriminos. This process is visually represented using ANSI escape sequences. +The program conceptually uses [Tetris](https://en.wikipedia.org/wiki/Tetris) as +an output device similar to a [line +printer](https://en.wikipedia.org/wiki/Line_printer). It restricts itself to +those operations that can be performed on the Tetris play-field: spawning, +rotating, positioning and dropping +[tetriminos](https://en.wikipedia.org/wiki/Tetromino). This process is visually +represented using ANSI escape sequences. ### ANSImation -The rate at which the program plays Tetris is completely determined by the rate in which the terminal application receives and displays the ANSI escape sequences. +The rate at which the program plays +[Tetris](https://en.wikipedia.org/wiki/Tetris) is completely determined by the +rate in which the terminal application receives and displays the [ANSI +escape](https://en.wikipedia.org/wiki/ANSI_escape_code) sequences. -To slowdown the output programmatically, introduce a delay immediately after the call to `fflush`. +To slow down the output programmatically, introduce a delay immediately after the +call to `fflush()` (N.B: see [birken.alt.c](birken.alt.c)). ### IOCCC Size Tool Bug -This program demonstrates how to exploit a bug in IOCCC size tool version 2013-07-30-v17. The first line of the program is reproduced below. +This program demonstrates how to exploit a bug in IOCCC size tool version +`2013-07-30-v17`. The first line of the program is reproduced below. char*_ = "'""/*"; @@ -148,58 +297,118 @@ $ ./iocccsize -i < prog.c 8 ``` -When that line is deleted from this program, the tool properly reports the secondary size limit of the program as 2048. +When that line is deleted from this program, the tool properly reports the +secondary size limit of the program as 2048. ```sh -$ ./iocccsize -i < prog.c +$ ./iocccsize -i < birken.c 2048 ``` -Although this bug provides an easy means of circumventing contest rule 2, as demonstrated from the size value, this entry is not necessarily striving for a 'worst abuse of the rules' award. +Although this bug provides an easy means of circumventing contest rule 2, as +demonstrated from the size value, this entry is not necessarily striving for a +'worst abuse of the rules' award. -###Obfuscations +### Obfuscations -This program is almost, but not quite, entirely unlike a demonstration of good programming practices. Contrary to other programs, an inspection of this one will certainly reveal that it possesses tea, not to mention an affinity for the constant 42. +This program is almost, but not quite, entirely unlike a demonstration of good +programming practices. Contrary to other programs, an inspection of this one +will certainly reveal that it possesses tea, not to mention an affinity for the +constant 42. -Variables are named and ordered to spell out, "Tetris", "ELORG", "DVK" and the aforementioned "Tea". ELORG is the abbreviation for Elektronorgtechnica, the former Soviet state owned computer organization that handled the worldwide Tetris intellectual property rights. DVK is the line of Soviet PDP-11-compatible personal computers capable of running Alexey Pajitnov's original 1984 Tetris prototype. +Variables are named and ordered to spell out, `"Tetris"`, `"ELORG"`, `"DVK"` and +the aforementioned `"Tea"`. +[ELORG](https://en.wikipedia.org/wiki/Elektronorgtechnica) is the abbreviation +for `Elektronorgtechnica`, the former Soviet state owned computer organization +that handled the worldwide Tetris intellectual property rights. DVK is the line +of Soviet PDP-11-compatible personal computers capable of running [Alexey +Pajitnov](https://en.wikipedia.org/wiki/Alexey_Pajitnov)'s original 1984 +[Tetris](https://en.wikipedia.org/wiki/Tetris) prototype. -Carefully selected variable names also yielded wonderful expressions like `l=0`, `O=0`, `O=1` and `while(O)`. "Tetris" also makes a second appearance of sorts: +Carefully selected variable names also yielded wonderful expressions like `l=0`, +`O=0`, `O=1` and `while(O)`. `"Tetris"` also makes a second appearance of +sorts: - [T][e][t]--; while(R+i) { s +```c +[T][e][t]--; while(R+i) { s +``` -The source is formatted to resemble the Tetris playfield midgame. It is also an homage to all the past IOCCC entries formatted as a compact block of text; the T, orientated appropriately to reflect its name and the first letter in the title of the game, is just a moment away from producing such a text block. +The source is formatted to resemble the +[Tetris](https://en.wikipedia.org/wiki/Tetris) play-field mid-game. It is also +an homage to all the [past IOCCC entries](/years.html) formatted as a compact +block of text; the `T`, orientated appropriately to reflect its name and the +first letter in the title of the game, is just a moment away from producing such +a text block. Three tables are encoded as separate strings within the program: -The first string stores the coordinates of the squares of the 19 distinct rotations of Tetriminos (see below). Since a Tetrimino is a chain of 4 squares, all Tetriminos fit within a 4×4 matrix. To determine the coordinates of the squares, the Tetrimino is pushed to the upper-left of the matrix. Each coordinate value requires 2 bits of storage. Consequentially, the four x-coordinates and the four y-coordinates were packed into separate octets. To convert the octets into valid ASCII characters, the squares were sorted such that the least significant bits stored the largest coordinate values. The results were offset by 35, the `#` character, which is 1 beyond the ASCII value of `"`, making it easier to pack into a string. None of the resultant values are beyond ASCII 127. The coordinates for all 19 rotations fit in a string of length 38. +The first string stores the coordinates of the squares of the 19 distinct +rotations of [tetriminos](https://en.wikipedia.org/wiki/Tetromino) (see below). +Since a tetrimino is a chain of 4 squares, all tetriminos fit within a 4x4 +matrix. To determine the coordinates of the squares, the tetrimino is pushed to +the upper-left of the matrix. Each coordinate value requires 2 bits of storage. +Consequentially, the four x-coordinates and the four y-coordinates were packed +into separate octets. To convert the octets into valid ASCII characters, the +squares were sorted such that the least significant bits stored the largest +coordinate values. The results were offset by 35, the `#` character, which is 1 +beyond the ASCII value of `"`, making it easier to pack into a string. None of +the resultant values are beyond ASCII 127. The coordinates for all 19 rotations +fit in a string of length 38. ![](rotations.png) -The second string stores the single square emitter patterns and the platform patterns. Each pattern is a sequence of pairs, { Tetrimino index, drop x-coordinate }. As mentioned, there are 19 distinct rotations, requiring 5 bits of storage for the Tetrimino index. Another 5 bits is required for the drop x-coordinate since there are 21 columns in the playfield. Necessarily, the pair is stored as 2 separate characters. By offsetting them by 40, the `(` character, the resultant string almost resembles a long and complex mathematical expression. The program takes advantage of mirror symmetry by only storing 10 single square emitter patterns and 5 platform patterns. The pattern lengths are not encoded within the string. Rather, they are embedded within the string decoding logic. +The second string stores the single square emitter patterns and the platform +patterns. Each pattern is a sequence of pairs, `{ tetrimino index, drop +x-coordinate }`. As mentioned, there are 19 distinct rotations, requiring 5 +bits of storage for the [tetrimino](https://en.wikipedia.org/wiki/Tetromino) +index. Another 5 bits is required for the drop x-coordinate since there are 21 +columns in the play-field. Necessarily, the pair is stored as 2 separate +characters. By offsetting them by 40, the `(` character, the resultant string +almost resembles a long and complex mathematical expression. The program takes +advantage of mirror symmetry by only storing 10 single square emitter patterns +and 5 platform patterns. The pattern lengths are not encoded within the string. +Rather, they are embedded within the string decoding logic. -The third string conceptually stores the default colors of the 19 rotations. A 3-bit value is assigned to each, covering the 7 possible colors. In addition, when a mirrored pattern is executed, J exchanges with L and S exchanges with Z, necessitating a second list of 3-bit color values. Pairs of color values (6 bits) fit comfortably into a character that is offset by `#`. The result is a string of length 19. +The third string conceptually stores the default colors of the 19 rotations. A +3-bit value is assigned to each, covering the 7 possible colors. In addition, +when a mirrored pattern is executed, `J` exchanges with `L` and `S` exchanges +with `Z`, necessitating a second list of 3-bit color values. Pairs of color +values (6 bits) fit comfortably into a character that is offset by `#`. The +result is a string of length 19. + +### Obfuscations The program is full of subtle obfuscations: -* The unary decrement operator is used in conjunction with global variable automatic zero initialization to set variables to `-1`. +* The unary decrement operator is used in conjunction with global variable +automatic zero initialization to set variables to `-1`. -* The boolean expression of the form, `x + 1`, is used multiple times to determine if a value is not `-1`. Similarly, expressions of the form `x - y` are used to determine if `x != y`. +* The boolean expression of the form, `x + 1`, is used multiple times to +determine if a value is not `-1`. Similarly, expressions of the form `x - y` +are used to determine if `x != y`. -* Several arrays store unrelated data in segments throughout the array to reduce named variables. +* Several arrays store unrelated data in segments throughout the array to reduce +named variables.. * The `x["..."]` trick appears once. * Variable `i` is less than necessary. -* A cursorily glance at the expressions `4&&L` and `m&&e==m` suggests that they always evaluate to true. +* A cursorily glance at the expressions `4&&L` and `m&&e==m` suggests that they +always evaluate to true. -* The varying single square emitter pattern lengths are resolved during string decoding using the clever expression, `(i & 3) - 3`, which identifies pattern 3 and 7 as longer. +* The varying single square emitter pattern lengths are resolved during string +decoding using the clever expression, `(i & 3) - 3`, which identifies pattern 3 +and 7 as longer. -* The file size of `prog.c` is a prime number. Deleting the first line also produces a prime-sized program. These properties do not qualify the program as a prime number generator. +* The file size of [birken.c](birken.c) is a prime number. Deleting the first +line also produces a prime-sized program. These properties do not qualify the +program as a prime number generator. ### Beyond Obfuscation -Due to the contest code size constraint, some optimizations reluctantly had to be omitted. For example, multi-square emitters are possible: +Due to the contest code size constraint, some optimizations reluctantly had to +be omitted. For example, multi-square emitters are possible: ![](multi2.gif) @@ -209,7 +418,8 @@ Due to the contest code size constraint, some optimizations reluctantly had to b ![](multi5.gif) -In fact, using dynamic programming and creative heuristics, real-time search is possible, enabling patterns like this: +In fact, using dynamic programming and creative heuristics, real-time search is +possible, enabling patterns like this: ![](triple0.gif) @@ -217,7 +427,11 @@ And, even this: ![](triple1.gif) -In addition, it is possible to extend the algorithm to 6 colors instead of just 3. This is achieved using I, S and Z to produce the protruding square. A series of rectangular regions are constructed above those Tetriminos to erode them down to a single emitted square. +In addition, it is possible to extend the algorithm to 6 colors instead of just 3. +This is achieved using `I`, `S` and `Z` to produce the protruding square. A +series of rectangular regions are constructed above those +[tetriminos](https://en.wikipedia.org/wiki/Tetromino) to erode them down to a +single emitted square. The details of these enhancements are left as an exercise to the reader. @@ -225,36 +439,81 @@ The details of these enhancements are left as an exercise to the reader. The following example files were created by the program author. They can be freely used and distributed. -* `format.txt` - The layout of the program -* `helloworld.txt` - Hello World, Tetris-style -* `hilbert.txt` - A graphic based on the Hilbert curve -* `ioccc.txt` - IOCCC -* `landon.txt` - Portrait of a man with glasses -* `leo.txt` - Portrait of a man without glasses -* `rhino.txt` - A purple rhinoceros -* `simon.txt` - Portrait of a man without hair +* [format.txt](format.txt) - The layout of the program +* [helloworld.txt](helloworld.txt) - Hello World, Tetris-style +* [hilbert.txt](hilbert.txt) - A graphic based on the Hilbert curve +* [ioccc.txt](ioccc.txt) - IOCCC +* [landon.txt](landon.txt) - Portrait of a man with glasses +* [leo.txt](leo.txt) - Portrait of a man without glasses +* [rhino.txt](rhino.txt) - A purple rhinoceros +* [simon.txt](simon.txt) - Portrait of a man without hair -The following files are based on graphics from non-free, copyrighted video games. The use of a limited number of textual representations of the graphics for the demonstration of this program qualifies as fair use as such files do not significantly impede the right of the copyright holder to sell the copyrighted material and it is not being used to generate profit in this context. The origin of each file is detailed below (character, game, company, year). +The following files are based on graphics from non-free, copyrighted video +games. The use of a limited number of textual representations of the graphics +for the demonstration of this program qualifies as fair use as such files do not +significantly impede the right of the copyright holder to sell the copyrighted +material and it is not being used to generate profit in this context. The +origin of each file is detailed below (character, game, company, year). -* `belmont.txt` - Simon Belmont, Castlevania, Konami, 1986 -* `bloober.txt` - Bloober, Super Mario Brothers, Nintendo, 1985 -* `bomberman.txt` - Bomberman, Bomberman, Hudson, 1983 -* `boo.txt` - Boo, Super Mario Brothers 3, Nintendo, 1988 -* `bub.txt` - Bub, Bubble Bobble, Taito, 1986 -* `cheepcheep.txt` - Cheep Cheep, Super Mario Brothers, Nintendo, 1985 -* `gurin.txt` - Gurin, Binary Land, Hudson, 1983 -* `koopaparatroopa.txt` - Koopa Paratroopa, Super Mario Brothers, Nintendo, 1985 -* `lakitu.txt` - Lakitu, Super Mario Brothers, Nintendo, 1985 -* `mario.txt` - Fire Mario, Super Mario Brothers, Nintendo, 1985 -* `mspacman.txt` - Ms. Pac-Man and Ghost, Ms. Pac-Man, Midway, 1982 -* `paranaplant.txt` - Piranha Plant, Super Mario Brothers, Nintendo, 1985 -* `samus.txt` - Samus Aran, Metroid, Nintendo/Intelligent Systems, 1986 -* `toad.txt` - Toad, Super Mario Brothers 2, Nintendo, 1987 +* [belmont.txt](belmont.txt) - [Simon +Belmont](https://en.wikipedia.org/wiki/Simon_Belmont), +[Castlevania](https://en.wikipedia.org/wiki/Castlevania_(1986_video_game)), +[Konami](https://en.wikipedia.org/wiki/Konami), 1986 + +* [bloober.txt](bloober.txt) - Bloober, [Super Mario +Brothers](https://www.mariowiki.com/Super_Mario_Bros.), +[Nintendo](https://en.wikipedia.org/wiki/Nintendo), 1985 + +* [bomberman.txt](bomberman.txt) - +[Bomberman](https://en.wikipedia.org/wiki/Bomberman), Bomberman, +[Hudson](https://en.wikipedia.org/wiki/Hudson_Soft), 1983 + +* [boo.txt](boo.txt) - [Boo](https://www.mariowiki.com/Boo), [Super Mario +Brothers 3](https://www.mariowiki.com/Super_Mario_Bros._3), Nintendo, 1988 + +* [bub.txt](bub.txt) - [Bub](https://bubblebobble.fandom.com/wiki/Bub), [Bubble +Bobble](https://en.wikipedia.org/wiki/Bubble_Bobble), Taito, 1986 + +* [cheepcheep.txt](cheepcheep.txt) - [Cheep +Cheep](https://www.mariowiki.com/Cheep_Cheep), Super Mario Brothers, Nintendo, 1985 + +* [gurin.txt](gurin.txt) - Gurin, [Binary +Land](https://en.wikipedia.org/wiki/Binary_Land), Hudson, 1983 + +* [koopaparatroopa.txt](koopaparatroopa.txt) - [Koopa +Paratroopa](https://www.mariowiki.com/Koopa_Paratroopa), Super Mario Brothers, +Nintendo, 1985 + +* [lakitu.txt](lakitu.txt) - [Lakitu](https://www.mariowiki.com/Lakitu), Super +Mario Brothers, Nintendo, 1985 + +* [mario.txt](mario.txt) - [Fire Mario](https://www.mariowiki.com/Fire_Mario), +Super Mario Brothers, Nintendo, 1985 + +* [mspacman.txt](mspacman.txt) - [Ms. +Pac-Man](https://pacman.fandom.com/wiki/Ms._Pac-Man) and Ghost, Ms. Pac-Man, +[Midway](https://en.wikipedia.org/wiki/Midway_Games), 1982 + +* [paranaplant.txt](paranaplant.txt) - [Piranha +Plant](https://www.mariowiki.com/Piranha_Plant), Super Mario Brothers, Nintendo, +1985 + +* [samus.txt](samus.txt) - [Samus +Aran](https://metroid.fandom.com/wiki/Samus_Aran), +[Metroid](https://metroid.fandom.com/wiki/Metroid_(game)), Nintendo/[Intelligent +Systems](https://en.wikipedia.org/wiki/Intelligent_Systems), 1986 + +* [toad.txt](toad.txt) - [Toad](https://www.mariowiki.com/Toad), Super Mario +Brothers 2, Nintendo, 1987 The origin of the remaining files are described below: -* `happyface.txt` - Based on a smiley; rights unknown -* `snoo.txt` - 8-bit version of Snoo, Reddit's alien mascot +* [happyface.txt](happyface.txt) - Based on a +[smiley](https://en.wikipedia.org/wiki/Smiley); original trademark of smiley +[Smiley Company](https://en.wikipedia.org/wiki/The_Smiley_Company) + +* [snoo.txt](snoo.txt) - 8-bit version of [Snoo](https://www.reddit.com/r/Snoo/), +[Reddit](https://www.reddit.com)'s alien mascot ## Copyright and CC BY-SA 4.0 License: diff --git a/2013/birken/birken.alt.c b/2013/birken/birken.alt.c new file mode 100644 index 000000000..e9f9e21bb --- /dev/null +++ b/2013/birken/birken.alt.c @@ -0,0 +1,50 @@ +char*_ = "'""/*"; +#include +#include +#define m 21 +#define o(l, k) for(l=0; lGP9$5-,#C?NX"]-35)>>t*3&7; o(e,4){ c[T] +[e][t]=("5'<$=$8)Ih$=h9i8'9" "t=)83)l4(99(g9>##>4(" [T+t+T]-35)>>e*2&3; +} } n(15) { s=T>9?m:(T&3)-3?15:36;o(e,s)o(t,2)c[T+19][e][t]="6*6,8*6.608.6264826668\ +865::(+;0(6+6-6/8,61638065678469.;88))()3(6,8*6.608.6264826668865:+;4)-*6-6/616365,\ +-6715690.5;,89,81+,(023096/:40(8-7751)2)65;695(855(+*8)+;4**+4(((6.608.626482666886\ +5:+;4+4)0(8)6/61638065678469.;88)-4,4*8+4(((60(/6264826668865:+;4-616365676993-9:54\ ++-14).;./347.+18*):1;-*0-975/)936.+:4*,80987(887(0(*)4.*""/4,4*8+4(((6264826668865:\ ++;4/4-4+8-4)0(8)6365678469.;88)1/(6*6,6.60626466686:8)8-8*818.8582/9863(+;/""*6,6.6\ +0626466686:4(8)8-8*818.8582/9863(+;/,6.60626466686:8-818.8582/9864*4+4(0())+;/.6062\ +6466686:8/8380/7844,4-4*4+4(0())69+;/0626466686:818582/9864.4/4,4-4*4+4(0())+;" [e+E ++e+t]-40; E+=s+s; } n(45){ if(T>i) { v(2,T,7); v(46,T,7); } v(2+T,44,7); } T=0; o(e, +42)o(t,m)h[T][e][t]--; while(R+i) { s = D=0; if (r-R) { n(19) if (G[R+i][T]+i) V=T/2 +; else if(G[R][T]+i) s++; if(s) { if(V>4){ V=9-V; D++; } V+=29; n(20) q(c[V][T][0],c +[V][T][i],D); } } n(19) if((L=G[R][T])+i) { O=T-L; e=O>9; t=e?18-O :O; o(K,((t&3)-3? +16:37)){ if(K){ L=c[t+19][K-i][0]; O=c[t+19][K-i][i] ; } q(L,O,K && e); } } if(s) q( +c[V][20][0], c[V][20][i], D); R--; } printf("\33[47;1f\33[?25h\33[40m"); return 0; } diff --git a/2013/birken/demo.sh b/2013/birken/demo.sh new file mode 100755 index 000000000..647c24f33 --- /dev/null +++ b/2013/birken/demo.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +make clobber everything 2>/dev/null + +if [[ -z "$BIRKEN" ]]; then + BIRKEN="birken" +fi + +trap "clear; exit" SIGINT + +for i in *.txt; do + NAME="$(echo "$i" | awk '{ print toupper(substr($1,1,1)) substr($1,2)}'|sed -e 's/\.txt//g' \ + -e 's/Ioccc/IOCCC/g' -e 's/Mspacman/Ms Pac-Man/g' -e 's/Helloworld/Hello World/g' \ + -e 's/Cheepcheep/Cheep Cheep/g' -e 's/Happyface/Happy Face/g' -e 's/Paranaplant/Piranha Plant/g' \ + -e 's/Koopaparatroopa/Koopa Paratroopa/g')" + read -r -n1 -p "Press any key to try $NAME: " + ./"${BIRKEN}" < "$i" + echo +done +clear diff --git a/2020/burton/README.md b/2020/burton/README.md index 342250a4d..a6c217e31 100644 --- a/2020/burton/README.md +++ b/2020/burton/README.md @@ -54,7 +54,7 @@ Can you find a pattern here? What happens if you specify different numbers? -This tiny one-liner is a bit-twiddlers delight! It does all of the work +This tiny one-liner is a bit-twiddler's delight! It does all of the work without looping. To understand how it works, a good place to start is to look at the hex @@ -91,7 +91,7 @@ Small, non-negative integers only. Useful range is `0 .. 511`, sorta, for LE; ` ASCII character set, 64-bit long longs are required. -v,a,r,i,a,b,l,e,s_NAME the operation. +v,a,r,i,a,b,l,e,s\_NAME the operation. No loops, no branches?!? diff --git a/bugs.md b/bugs.md index a3f819a4d..a957e7bb6 100644 --- a/bugs.md +++ b/bugs.md @@ -647,8 +647,9 @@ This will be fixed in time but it's noted here for now. ## 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. +opened for writing the program will very likely crash or do something funny. +This is not a bug but a feature. Please do not fix this except for the +challenge to yourself. Please also note that for `clang` you have to use [dds.alt](1991/dds/dds.alt.c) not [dds.c](1991/dds/dds.c). @@ -1903,45 +1904,126 @@ tends to result in empty output. ## [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`: +This does not appear to work with macOS, resulting in a segfault (and sometimes +a bus error). + +We're not +sure if this is to do with the Apple silicon chip or not but it seems like it +_might_ (see Apple resources below) be but it could also be a wider problem with macOS. It appears that +Apple does not allow certain combinations of memory protections with the arm64 +processor. + +[Cody Boone Ferguson](/winners.html#Cody_Boone_Ferguson) tried some of the +workarounds but at this time he could not get it to work. He offers some earlier +debugging sessions below as well as a resource from the author as well as some +resources on Apple's website should anyone wish to take a crack at it. He might +address it later. + +### Debugging + +At first glance it appeared to be that it might be the function pointers or the +fact it is trying to execute code in memory (as noted above). The function +pointers were changed a bit but this has not helped solve the problem with +macOS. A few things that were noticed depending on `asan` sanitisers specified. +With `address` in linux: + ``` -==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 () +richards.c:101:9: runtime error: null pointer passed as argument 2, which is declared to never be null +``` -Address 0x00016d368d08 is located in stack of thread T0 at offset 40 in frame - #0 0x102b1dae8 in rd richards.c:125 +but it actually works. This code is: - This frame has 1 object(s): - [32, 40) 'a' (line 126) <== Memory access at offset 40 overflows this variable +```c + } else + p++; + W(c)} /* LINE 101 */ + } +``` + +Okay but what about argument 2? Well `W` is defined as: + +```c +#define W(c) e=memmove(e,x[(u)c], y[(u)c])+y[(u)c]; +``` + +so it would appear that + +```c +x[(u)c] +``` + +(at least in my tired head?) is NULL. But why does it work then? + +NOTE: `u` is `int`. + +Under macOS (with the arm64 chip) we get: + +``` +UndefinedBehaviorSanitizer:DEADLYSIGNAL +==10834==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0xffffffffffffffff (pc 0x00019f446748 bp 0x00016f353100 sp 0x00016f352b90 T139066) +==10834==The signal is caused by a WRITE memory access. + #0 0x19f446748 in _platform_memmove+0xa8 (libsystem_platform.dylib:arm64e+0x3748) (BuildId: 756cd10d62a032839e57cbaa810c95ac32000000200000000100000000030d00) + #1 0x100c33c2c in main richards.c:202 + #2 0x19f0bff24 () + +==10834==Register values: + x[0] = 0xffffffffffffffff x[1] = 0x0000000100ab18c1 x[2] = 0x00000000000000cf x[3] = 0x0000000000000000 + x[4] = 0x0000000100ab18a1 x[5] = 0x0000000000000001 x[6] = 0x000000000000000a x[7] = 0x0000000000000000 + x[8] = 0x00000001015972b8 x[9] = 0xffffffffffffffff x[10] = 0x0000000000000001 x[11] = 0x00000000000001f0 +x[12] = 0x0000000000000001 x[13] = 0x00000000000003e0 x[14] = 0x0000000000000001 x[15] = 0x0000000000000084 +x[16] = 0x000000019f4466a0 x[17] = 0x00000001ff3ad908 x[18] = 0x0000000000000000 x[19] = 0x0000000100c32a80 +x[20] = 0x00000001017e0000 x[21] = 0x00000001017e1910 x[22] = 0x000000016f353530 x[23] = 0x000000019f13a366 +x[24] = 0x000000016f3534b0 x[25] = 0x0000000000000001 x[26] = 0x0000000000000000 x[27] = 0x0000000000000000 +x[28] = 0x0000000000000000 fp = 0x000000016f353100 lr = 0x0000000100aaf880 sp = 0x000000016f352b90 +UndefinedBehaviorSanitizer can not provide additional info. +SUMMARY: UndefinedBehaviorSanitizer: SEGV (libsystem_platform.dylib:arm64e+0x3748) (BuildId: 756cd10d62a032839e57cbaa810c95ac32000000200000000100000000030d00) in _platform_memmove+0xa8 +==10834==ABORTING +``` + +and naturally it does not work. + +Adding the proper `PROT_WRITE` constant to the `mmap()` call does not seem to +help. Of course with the address this is not surprising so why is a different +address allocated in macOS? Or is it? + +Now with `address` sanitiser both linux and macOS crash at: + +``` +================================================================= +==10983==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x00016f8d5e78 at pc 0x0001005dd910 bp 0x00016f8d5cd0 sp 0x00016f8d5cc8 +READ of size 8 at 0x00016f8d5e78 thread T0 + #0 0x1005dd90c in rd richards.c:132 + #1 0x1005ddf8c in re richards.c:149 + #2 0x1005110a0 in t richards.c:108 + #3 0x1005df72c in main richards.c:189 + #4 0x19f0bff24 () + +Address 0x00016f8d5e78 is located in stack of thread T0 at offset 56 in frame + #0 0x1005dd678 in rd richards.c:129 + + This frame has 2 object(s): + [32, 36) 'v.addr' + [48, 56) 'a' (line 130) <== Memory access at offset 56 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 +SUMMARY: AddressSanitizer: stack-buffer-overflow richards.c:132 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 + 0x00702df3ab70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702df3ab80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702df3ab90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702df3aba0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702df3abb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +=>0x00702df3abc0: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 04 f2 00[f3] + 0x00702df3abd0: f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702df3abe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702df3abf0: 00 00 00 00 f1 f1 f1 f1 00 f3 f3 f3 00 00 00 00 + 0x00702df3ac00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x00702df3ac10: 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 + Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 @@ -1958,35 +2040,98 @@ Shadow byte legend (one shadow byte represents 8 application bytes): ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb -==32361==ABORTING - +==10983==ABORTING +/bin/bash: line 1: 10983 Abort trap: 6 ./richards ``` -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: +which corresponds to the code: ```c - o *a = 0, **b = &a, **c = b + 24; +o rd(u v) +{ + o *a = 0, **b = &a, **c = b + 32; x[v] = w; - for (; b < c && (*b < (o *)w || *b > (o *) T || *b == (long) v); b++); + for (; b < c && (*b < (o *)w || *b > (o *) T || *b == &v); b++); /* LINE 132 */ ``` -where `o` is a `void`. +but this seems to not necessarily be relevant since without it it works in +linux. + +A warning of interest when compiling is: + +``` + +richards.c:169:15: warning: incompatible pointer types initializing 'f *' (aka 'void (**)(volatile void *)') with an expression of type 'o ()' (aka 'void ()') [-Wincompatible-pointer-types] +f *lib1[] = { T, T, T, T, T } ; + +... + +richards.c:170:15: warning: incompatible pointer types initializing 'f *' (aka 'void (**)(volatile void *)') with an expression of type 'o ()' (aka 'void ()') [-Wincompatible-pointer-types] +f *lib2[] = { T, ld, lp, lx, l1 } ; + ^ +richards.c:170:18: warning: incompatible pointer types initializing 'f *' (aka 'void (**)(volatile void *)') with an expression of type 'void (volatile dt)' (aka 'void (struct (unnamed at richards.c:36:3) *volatile)') [-Wincompatible-pointer-types] +f *lib2[] = { T, ld, lp, lx, l1 } ; + ^~ +richards.c:170:22: warning: incompatible pointer types initializing 'f *' (aka 'void (**)(volatile void *)') with an expression of type 'void (volatile dt)' (aka 'void (struct (unnamed at richards.c:36:3) *volatile)') [-Wincompatible-pointer-types] +f *lib2[] = { T, ld, lp, lx, l1 } ; + ^~ +richards.c:170:26: warning: incompatible pointer types initializing 'f *' (aka 'void (**)(volatile void *)') with an expression of type 'void (volatile dt)' (aka 'void (struct (unnamed at richards.c:36:3) *volatile)') [-Wincompatible-pointer-types] +f *lib2[] = { T, ld, lp, lx, l1 } ; + ^~ +richards.c:170:30: warning: incompatible pointer types initializing 'f *' (aka 'void (**)(volatile void *)') with an expression of type 'void (volatile dt)' (aka 'void (struct (unnamed at richards.c:36:3) *volatile)') [-Wincompatible-pointer-types] +f *lib2[] = { T, ld, lp, lx, l1 } ; + ^~ +``` + +This can be fixed easily enough however but it doesn't appear to matter in this +case. + +### Resources + +#### More from the author + +The author has more about the entry at +. + +#### Apple resources + +[Porting Just-In-Time Compilers to Apple +Silicon](https://developer.apple.com/documentation/apple-silicon/porting-just-in-time-compilers-to-apple-silicon?language=objc) + +[Allow Execution of JIT-compiled Code +Entitlement](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_cs_allow-jit?language=objc) + +Looking at + +Cody noticed a curious thing in the `mprotect()` function: `#if +CONFIG_DYNAMIC_CODE_SIGNING` and the protection variable has the +`VM_PROT_TRUSTED` set it might allow overriding the problem but this is +unconfirmed and it's not known when `CONFIG_DYNAMIC_CODE_SIGNING` would be +defined. Do you have a fix? We welcome it! -## [2011/vik](2012/vik/vik.c) ([README.md](2012/vik/README.md)) + +## [2011/vik](2011/vik/vik.c) ([README.md](2011/vik/README.md)) ## STATUS: INABIAF - please **DO NOT** fix -The author stated that the program will crash if no argument is passed tot he +The author stated that the program will crash if no argument is passed to the program though we note that your computer might also [halt and catch fire](https://en.wikipedia.org/wiki/Halt_and_Catch_Fire_(computing)) :-) # 2012 +## [2012/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 to the +program or if invalid arguments or images of mismatching sizes or unsupported +pixel formats though we note that your computer might also [halt and catch +fire](https://en.wikipedia.org/wiki/Halt_and_Catch_Fire_(computing)) :-) + + # 2013 diff --git a/tmp/winners.csv b/tmp/winners.csv index d8d21919d..60a229b5f 100644 --- a/tmp/winners.csv +++ b/tmp/winners.csv @@ -99,7 +99,7 @@ Jens Schweikhardt,Jens_Schweikhardt,http://www.schweikhardt.net,null,schweikh@sc Jetro Lauha,Jetro_Lauha,http://jet.ro,null,null,FI,null,null Jim Hague,Jim_Hague,http://www.oxinet.co.uk/jim,null,jim.hague@acm.org,UK,null,null John Dalbec,John_Dalbec,https://jpdalbec.people.ysu.edu,null,jdalbec@cboss.com,null,null,null -John Tromp,John_Tromp,http://tromp.github.io/,null,john.tromp@gmail.com,null,null,null +John Tromp,John_Tromp,http://tromp.github.io/,john.tromp@gmail.com,null,null,null John Williams,John_Williams,null,null,williams@morinda.com,null,null,null Jon Thingvold,Jon_Thingvold,null,null,jon.thingvold@usit.uio.no,null,null,null Jonathan Hoyle,Jonathan_Hoyle,http://www.jonhoyle.com,null,jonhoyle@mac.com,null,null,null @@ -164,7 +164,7 @@ Sean Barrett,Sean_Barrett,http://world.std.com/~buzzard,null,buzzard@world.std.c Sean Dorward,Sean_Dorward,null,null,null,null,null,null Sebastian Deorowicz,Sebastian_Deorowicz,http://sun.aei.polsl.pl/~sdeor/,null,sdeorowicz@gmail.com,null,null,null Selene Makarios,Selene_Makarios,http://www.bungalow.com/,null,null,null,null,null -Seonghoon Kang,Seonghoon_Kang,null,null,kang.seonghoon@mearie.org,null,null,null +Seonghoon Kang,Seonghoon_Kang,null,http://mearie.org,kang.seonghoon@mearie.org,null,null,null Shinichiro Hamaji,Shinichiro_Hamaji,null,shinichiro.hamaji@gmail.com,null,null,null Sjoerd Mullender,Sjoerd_Mullender,http://www.cwi.nl/~sjoerd/,null,Sjoerd.Mullender@cwi.nl,null,null,null Someone Anonymous,Anonymous_2015,null,null,hirekokeshi@gmail.com,null,@hirekoke,null diff --git a/winners.html b/winners.html index 4457e8f28..35d55256c 100644 --- a/winners.html +++ b/winners.html @@ -685,7 +685,8 @@ Contest