Remove hint.html and index.html
As per discussions on GitHub the index.html and hint.html files should be deleted in favour of README.md files (from any .text/.txt/.markdown/.md files which will be turned into README.md in an upcoming commit).
This commit is contained in:
1 parent
ee8a36310f
commit
77fb0f11a2
143 files changed
-28606
No files matched your search
@@ -1,154 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="GENERATOR" content="mkd2html 2.1.5a DL=DISCOUNT">
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
|
||||
<link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="../hint.css">
|
||||
<title>Most cacophonic</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Most cacophonic</h1>
|
||||
|
||||
<p>Anton Älgmyr<br>
|
||||
Twitter: @aalgmyr</p>
|
||||
|
||||
<h2>Judges' comments:</h2>
|
||||
|
||||
<h3>To use:</h3>
|
||||
|
||||
<pre><code>make
|
||||
|
||||
cat prog.c | ./prog # Printing garbage might break your font
|
||||
./prog <file1> <file2> > out.raw
|
||||
./prog -d 2 0 out.raw # Decode the first (0th) channel out of two
|
||||
</code></pre>
|
||||
|
||||
<h3>To try:</h3>
|
||||
|
||||
<pre><code>./prog -h | ./prog -d 1 0
|
||||
|
||||
# Who needs cat?
|
||||
./prog prog.c | ./prog -d 1 0
|
||||
|
||||
# Assuming ALSA
|
||||
echo '<<<<<< /\_/\_/\ _-_-_-_ !!!!! :.:.:.: >>>>>> ****** ~~~~~~~' |
|
||||
./prog | aplay -c1 -fFLOAT_LE -r44100
|
||||
|
||||
# Assuming sox
|
||||
echo -n ' MENE MENE TEKEL UPHARSIN ' | ./prog |
|
||||
sox -t raw -c 1 -r 44100 -L -e floating-point -b 32 - -n spectrogram -d 10 -X 300
|
||||
</code></pre>
|
||||
|
||||
<h3>Selected Judges Remarks:</h3>
|
||||
|
||||
<p>Be warned, this is not your garden variety text-to-speech program! Earplugs are advised,
|
||||
or at least a handy and well-tested volume knob.</p>
|
||||
|
||||
<p>Pixels are numbered, amplitudes are weighed, frequencies are divided,
|
||||
and the message can be displayed in fiery letters, but don’t be alarmed.</p>
|
||||
|
||||
<p>How does decoding of the waveform work? Can you encode an arbitrary text in a sound sample?</p>
|
||||
|
||||
<h2>Author’s comments:</h2>
|
||||
|
||||
<h1>What is this?</h1>
|
||||
|
||||
<p>To put it brief, this entry is akin to a sound based cat. It takes characters as input and outputs them into frequency space as audio. The entry also supports decoding the produced waveforms using the <code>-d</code> flag. Usage instructions is output if run with the <code>-h</code> flag, albeit not in an immediately legible format.</p>
|
||||
|
||||
<h2>Details</h2>
|
||||
|
||||
<p>In normal operation, the entry reads characters from one or more sources. If the <code>-h</code> flag is given, usage instructions is used as a source. Else if file paths are present as arguments those will be used. Else stdin is used.</p>
|
||||
|
||||
<p>If a character is part of the supported subset of ASCII <code>{10, 32-126}</code> then that character is output into frequency space of an audio signal (44.1 kHz single precision float, endianness should depend on system endianness) through stdout. Any other character will be interpreted and outputted as a space.</p>
|
||||
|
||||
<p>Characters are printed using a (slightly modified) pixel font based on <a href="https://github.com/hchargois/gohufont">gohufont</a>. Pixels are drawn using crosses in frequency space, achieved by simultaneous up and down chirps.</p>
|
||||
|
||||
<p>Each input source is designated its own channel in the output (one float per channel per time step in the output) so if you have a surround sound system you could listen to a cacophony of chirpy characters.</p>
|
||||
|
||||
<p>Interestingly, with training you might actually be able to tell characters just from hearing. But even without training you can easily read along with the printed characters and have the sound make sense with the look of the characters.</p>
|
||||
|
||||
<p>See image spoiler.png for an example spectrogram.</p>
|
||||
|
||||
<h2>Limitations</h2>
|
||||
|
||||
<p>There is no error checking done when opening files, so expect segfaults if you provide the wrong path to a file.</p>
|
||||
|
||||
<p>This program is bound to misbehave if int is less than 32 bits.</p>
|
||||
|
||||
<p>Flags will only be interpreted correctly if they are the first argument. Reading a file named <code>-d</code> or <code>-h</code> is fully possible if it is not the first file provided, even though I am not sure why you would want to do that.</p>
|
||||
|
||||
<p>Providing invalid/unexpected arguments to the decode flag will result in odd behavior. Some erroneous arguments cause segfaults (negative number of channels, channel id outside valid range). One argument in particular causes an infinite loop printing whitespace.</p>
|
||||
|
||||
<h1>Techniques</h1>
|
||||
|
||||
<h2>Obfuscation</h2>
|
||||
|
||||
<p>A lot of the obfuscations done came naturally from trying to appease the size tool. To name some:</p>
|
||||
|
||||
<ul>
|
||||
<li>One character names</li>
|
||||
<li>Merging of related (and not so related) arithmetic operations</li>
|
||||
<li>Short circuiting for flow control to replace some <code>if</code>s</li>
|
||||
<li>Some <code>#defines</code>, sadly</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>On the intersection of size and obfuscation is the data encoding, which was quite fun to design.</p>
|
||||
|
||||
<p>Some additional obfuscation was done to mathematical formulas. Somewhat known expressions was transformed into equivalent but less recognizable counterparts.</p>
|
||||
|
||||
<p>I have tried to avoid intentional red herrings in the code, although fishy statements are plentiful.</p>
|
||||
|
||||
<h2>Data encoding</h2>
|
||||
|
||||
<p>The large string in the beginning of the source file contains font data, encoded in base64 using characters in the range <code>' '</code> to <code>'_'</code>. The space was chosen as the zero because the data contains a lot of zeroes, and quite helpfully the size tool ignores whitespace even in strings. Without this fact the program would have been too large and the decoding feature would have had to go. Fortunately this hole in the size spec was readily available. :)</p>
|
||||
|
||||
<p>Characters in the font (5x8 pixels, 40 bits) is packed into 7 base64 digits (which was a pain to decode in minimal code).</p>
|
||||
|
||||
<h2>Math</h2>
|
||||
|
||||
<p>Note that even though floats are used for the waveforms, the standard math library is not used at all! Most arithmetic is done purely on integers. The only major exception is generating a table of sine values which are interpolated to give high resolution waveforms. Can you see when the generation is triggered, and how it is done?</p>
|
||||
|
||||
<p>A critical issue encountered was that having abrupt starts and ends of signals cause a lot of problems with spectral leakage which makes spectrograms hard to read and audio painful to listen to. To reduce spectral leakage a windowing function was used. Although the one used is quite well known, it is not in a form that should be familiar to anyone. What looks like a polynomial and quacks like a polynomial might not actually be a polynomial, at least not deep inside.</p>
|
||||
|
||||
<h2>Printing a string</h2>
|
||||
|
||||
<p>The program was written to deal exclusively with file descriptors, so how would one go about printing a char array not from a file descriptor without adding additional logic? Answer: <code>ungetc</code> into stdin, one char at a time (to be standards compliant). This is used to print the usage instructions.</p>
|
||||
|
||||
<h1>Compilation warnings</h1>
|
||||
|
||||
<p>Compiling using</p>
|
||||
|
||||
<pre><code>gcc -Wall -Wextra -pedantic
|
||||
</code></pre>
|
||||
|
||||
<p>gives only <code>-Wmisleading-indentation</code> which is sensible considering the source code. While</p>
|
||||
|
||||
<pre><code>clang -Wall -Wextra -pedantic
|
||||
</code></pre>
|
||||
|
||||
<p>is a bit more pessimistic and gives <code>-Wempty-body</code> (I like loops without bodies), <code>-Wstring-plus-int</code> (since apparently some people think string+int is a concatenation) and one of the weirder warnings I have seen from me splitting a negative constant with whitespace. Compiling using</p>
|
||||
|
||||
<pre><code>clang -Wall -Wextra -pedantic -Weverything
|
||||
</code></pre>
|
||||
|
||||
<p>produces a few pagefuls of warnings and makes me feel generally bad about myself. :(</p>
|
||||
|
||||
<h1>Misc</h1>
|
||||
|
||||
<p>The reported size of the source code using the size tool is very intentionally 2018.</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<TABLE><TR>
|
||||
<TD><a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/3.0/88x31.png" /></a></TD>
|
||||
<TD><P>© Copyright 1984-2018,
|
||||
<A HREF="/judges.html">Leo Broukhis, Simon Cooper, Landon Curt Noll</A>
|
||||
- All rights reserved<BR>
|
||||
This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
|
||||
<TD> <!--<a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
|
||||
</TR></TABLE>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,91 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="GENERATOR" content="mkd2html 2.1.5a DL=DISCOUNT">
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
|
||||
<link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="../hint.css">
|
||||
<title>Most able to divine code gaps</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Most able to divine code gaps</h1>
|
||||
|
||||
<p>Derek Anderson</p>
|
||||
|
||||
<h2>Judges' comments:</h2>
|
||||
|
||||
<h3>To use:</h3>
|
||||
|
||||
<pre><code>make
|
||||
./prog < textfile
|
||||
</code></pre>
|
||||
|
||||
<h3>Try:</h3>
|
||||
|
||||
<pre><code>./prog < prog.c
|
||||
./prog < prog.orig.c
|
||||
./prog < hint.text
|
||||
</code></pre>
|
||||
|
||||
<h3>Selected Judges Remarks:</h3>
|
||||
|
||||
<p>With this entry, you won’t need to turn your monitor <a href="http://en.wikipedia.org/wiki/River_%28typography%29">upside down</a>!</p>
|
||||
|
||||
<p>Compare <code>prog.c</code> and <code>prog.orig.c</code> and find out why we had to modify the entry, and what confused the author
|
||||
(see the author’s remarks). No, it was not the shape of the Roman V that we, or the compiler, didn’t like.</p>
|
||||
|
||||
<h2>Author’s comments:</h2>
|
||||
|
||||
<h2>Compiling the program</h2>
|
||||
|
||||
<pre><code>gcc -Wall -Wextra -Wpedantic -O3 -std=c11 prog.c -o prog
|
||||
</code></pre>
|
||||
|
||||
<p>Also works with a standard of c99, but c90/c89 will not compile due to
|
||||
for loop initial declarations, along with additional warnings about
|
||||
variable length arrays and lack of a return statement.</p>
|
||||
|
||||
<h2>Additional info</h2>
|
||||
|
||||
<p>This small program, when given text on stdin, will produce a pattern of
|
||||
squiggly lines. This pattern is deterministic, and it shouldn’t be too
|
||||
difficult to determine from whence they come. There is even a comment
|
||||
that describes the highlighted phenomena in the source, for those that
|
||||
require a small nudge. With denser text blocks, such as an essay or
|
||||
similar prose, the output can be rather pretty, in an chaotic emergence
|
||||
sort of way. Try using this file, or the source file as inputs.</p>
|
||||
|
||||
<p>In its current form, this program can handle lines of length 255; to
|
||||
adjust this limit, change the variable <code>a</code> at the top of the source.
|
||||
Other adjustments, such as the exact printed characters, are rather
|
||||
easy, once sufficient reverse engineering has occurred. Improvements
|
||||
such as proper handling of tabs are left as an exercise to the reader.</p>
|
||||
|
||||
<p>In developing this program, the author found a potentially interesting
|
||||
bug. If the expression <code>(j=k,j)</code> (near the middle of the source) is
|
||||
changed to <code>(j=k,k)</code>, the program produces different output. The author
|
||||
used compiler gcc 5.4.0, compiled for x86_64-linux-gnu. Enabling or
|
||||
disabling optimization produces the same results. The author is not
|
||||
sure who is the culprit, but instead shrugged and moved on with life.
|
||||
Of course, YMMV with your own environment.</p>
|
||||
|
||||
<p>The structure of this program, as you may have deduced, is two for
|
||||
loops, one nested in the other. There is also a bunch of direct
|
||||
variable assignment, such as <code>j=k</code>. There is some filler fluff, such as
|
||||
<code>0-0+0</code>, but all that sort should be rather easy to spot. It was mostly
|
||||
added for the purpose of making certain things line up right, and only
|
||||
secondarily to obfuscate.</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<TABLE><TR>
|
||||
<TD><a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/3.0/88x31.png" /></a></TD>
|
||||
<TD><P>© Copyright 1984-2018,
|
||||
<A HREF="/judges.html">Leo Broukhis, Simon Cooper, Landon Curt Noll</A>
|
||||
- All rights reserved<BR>
|
||||
This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
|
||||
<TD> <!--<a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
|
||||
</TR></TABLE>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,105 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="GENERATOR" content="mkd2html 2.1.5a DL=DISCOUNT">
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
|
||||
<link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="../hint.css">
|
||||
<title>Most inflationary</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Most inflationary</h1>
|
||||
|
||||
<p>Fabrice Bellard<br>
|
||||
<a href="https://bellard.org/">https://bellard.org/</a></p>
|
||||
|
||||
<h2>Judges' comments:</h2>
|
||||
|
||||
<h3>To use:</h3>
|
||||
|
||||
<pre><code>make
|
||||
./prog > lena.ppm
|
||||
</code></pre>
|
||||
|
||||
<h3>Try:</h3>
|
||||
|
||||
<pre><code>eog lena.ppm # On Linux
|
||||
preview lena.ppm # On MacOS
|
||||
|
||||
wget http://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png
|
||||
pngtopnm < Lenna.png | pnmscale 0.25 | cjpeg -arithmetic -dct float -quality 14 > small.jpg
|
||||
</code></pre>
|
||||
|
||||
<p>The file <code>small.jpg</code> will be approximately of the same size as the raw image data
|
||||
in the program. Compare the level of the detail and the artifacts of
|
||||
<code>small.jpg</code> and <code>lena.ppm</code>.</p>
|
||||
|
||||
<h3>Selected Judges Remarks:</h3>
|
||||
|
||||
<p>Compressing images is just a matter of simple arithmetic and some magic, isn’t it?</p>
|
||||
|
||||
<p>We could understand some of the arithmetic but none of the magic.</p>
|
||||
|
||||
<p>Deciphering the mechanism used for data encoding to make use
|
||||
of the whitespaces, braces and semicolons should be a slightly easier task.</p>
|
||||
|
||||
<h2>Author’s comments:</h2>
|
||||
|
||||
<p>This program outputs a 128x128 RGB image file to the standard output
|
||||
using the portable pixmap file format (PPM). It contains the famous
|
||||
“Lena” image which is used in many image compression tests.</p>
|
||||
|
||||
<p>The uncompressed image is 12 times larger than the source code of the
|
||||
program which includes the image data and the complete decoder. The
|
||||
actual image data is 1220 byte long, which gives a compression ratio
|
||||
of 40. Using a JPEG-like algorithm would not be enough to reach this
|
||||
level of compression (the Lena image would be barely recognizable). So
|
||||
the algorithm is based on the latest advances in image compression. It
|
||||
includes the following features:</p>
|
||||
|
||||
<ul>
|
||||
<li>DCT transform with variable block size (4x4, 8x8, 16x16 and 32x32)</li>
|
||||
<li>DC and directional predictors</li>
|
||||
<li>arithmetic coding</li>
|
||||
<li>YCgCo color space.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>The image data is encoded to a C string with some tricks to make the
|
||||
best use of the IOCCC size constraints. The identifiers were shortened
|
||||
to a single letter to save space. No specific obfuscation was needed
|
||||
as the algorithms already have a significant complexity.</p>
|
||||
|
||||
<p>Although the program was optimized to decompress its built-in image,
|
||||
it accepts to decompress image files from its standard
|
||||
input. Examples:</p>
|
||||
|
||||
<pre><code>./prog d < lena512.bin > lena512.ppm
|
||||
./prog d < fruits.bin > fruits.ppm
|
||||
./prog d < vintage_cars.bin > vintage_cars.ppm
|
||||
</code></pre>
|
||||
|
||||
<p>The original images for <a href="https://commons.wikimedia.org/wiki/File%3AFruits_oranges%2C_jardin_japonais_2.JPG">fruits</a> and <a href="https://commons.wikimedia.org/wiki/File%3ARed_Bull_Jungfrau_Stafette%2C_10th_stage_-_vintage_cars_%282%29.jpg">vintage cars</a> come from
|
||||
Wikipedia and were resized to a width of 1024 pixels. Warning: the
|
||||
program is not protected against invalid input.</p>
|
||||
|
||||
<p>The program should be portable on any Unix system. On Windows the line
|
||||
“<em>setmode(0, 32768); </em>setmode(1, 32768);” must be added at the start of
|
||||
the main() function to avoid unwanted carriage return characters in
|
||||
the output.</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<hr />
|
||||
|
||||
<TABLE><TR>
|
||||
<TD><a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/3.0/88x31.png" /></a></TD>
|
||||
<TD><P>© Copyright 1984-2018,
|
||||
<A HREF="/judges.html">Leo Broukhis, Simon Cooper, Landon Curt Noll</A>
|
||||
- All rights reserved<BR>
|
||||
This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
|
||||
<TD> <!--<a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
|
||||
</TR></TABLE>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,246 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="GENERATOR" content="mkd2html 2.1.5a DL=DISCOUNT">
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
|
||||
<link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="../hint.css">
|
||||
<title>Best one-liner</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Best one-liner</h1>
|
||||
|
||||
<p>Dave Burton<br>
|
||||
<a href="http://ioccc.snox.net">http://ioccc.snox.net</a></p>
|
||||
|
||||
<h2>Judges' comments:</h2>
|
||||
|
||||
<h3>To use:</h3>
|
||||
|
||||
<pre><code>make
|
||||
./prog < any-file
|
||||
</code></pre>
|
||||
|
||||
<h3>Try:</h3>
|
||||
|
||||
<pre><code>./prog < prog
|
||||
./prog < prog.c
|
||||
</code></pre>
|
||||
|
||||
<h3>Selected Judges Remarks:</h3>
|
||||
|
||||
<p>One line, one array, one loop and one statement but it prints many bytes. It won.</p>
|
||||
|
||||
<h2>Author’s comments:</h2>
|
||||
|
||||
<p>Feed this anything on stdin.</p>
|
||||
|
||||
<p>The included script may be used as a driver program for this entry.
|
||||
It adds several nice-to-have features, and allows salt-to-taste customizability.</p>
|
||||
|
||||
<p>This code has been compiled and tested on:</p>
|
||||
|
||||
<ul>
|
||||
<li>OSX-10.11, gcc 4.2.1 and clang 3.0, -O0 and -O3</li>
|
||||
<li>X86-Linux, gcc 4.1.2 and 4.8.4, -O0 and -O3</li>
|
||||
<li>ARM-QEMU, gcc 4.8.4, -O0 and -O3</li>
|
||||
<li>X86-FreeBSD 10.3, clang 3.4.1, -O0 and -O3</li>
|
||||
<li>TCC 0.9.26 (x86-64) (used as a proxy for <a href="http://ioccc.org/years.html#2001_bellard">2001/bellard</a>)</li>
|
||||
<li>UNIX V7 pcc (Johnson’s C compiler) on a <a href="http://simh.trailing-edge.com/">simulated PDP-11/45</a>
|
||||
(see spoiler for further detail)</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<div style="margin-bottom:60em;margin-top:4em"><strong>Spoiler below; scroll down.</strong></div>
|
||||
|
||||
|
||||
<h2>SPOILER</h2>
|
||||
|
||||
<p>This started life as a personal challenge: write the shortest hex dump utility in C.</p>
|
||||
|
||||
<p>The self-imposed ground rules in the hunt for shortest:
|
||||
the code has to output correctly,
|
||||
no extraneous newlines, the code must be portable,
|
||||
and without bypassing the solution using execve(2),
|
||||
or functions built upon it (system(3), popen(3), etc). E.g:</p>
|
||||
|
||||
<pre><code>main(){system("hd");} // it's turtles all the way down!
|
||||
</code></pre>
|
||||
|
||||
<p>is not acceptable.
|
||||
And, “output correctly” is the output format of this entry. QED.</p>
|
||||
|
||||
<p>Early attempts ended up at a reasonably short 157 characters.
|
||||
This was too long for a one-liner, so it had to be formatted as something more interesting.
|
||||
This solution is pleasing, but a true one-liner was the hoped-for goal.
|
||||
Here is the 157 character version in it’s entirety:</p>
|
||||
|
||||
<pre><code>char O,o[ 20];L(O){
|
||||
putchar ( O+ 48+39 *(9<
|
||||
O));} I(O) {L(~ 15);
|
||||
O|| puts(o);} main (l){
|
||||
for(;~(l=getchar()) ;I(O
|
||||
&=15 ))o[ O++ ]=4<
|
||||
(4^l >>5) ?l: 46,L
|
||||
(l>> 4),L (l&15);O&&
|
||||
I(o[ O]=0 );}//157c
|
||||
</code></pre>
|
||||
|
||||
<p>While thinking about this in the shower (you are not the only one that does this!)
|
||||
came the idea which reduced the code to just 119 chars.
|
||||
This dramatic reduction started to feel close to minimal, and the hunt resumed.
|
||||
The progression to the present size is interesting,
|
||||
and it is interesting that the same algorithm can be expressed so differently
|
||||
by slight rearrangement of its parts.</p>
|
||||
|
||||
<pre><code>// 119
|
||||
char O,o[20];main(l){for(;~(l=getchar());O||puts(o))o[O++]=isprint(l)?l:46,O&=15,printf("%02x ",l);O[o]=0;O&&puts(o);}
|
||||
// 116
|
||||
char O,o[20];main(l){for(;O++[o]=~(l=getchar())?4<(4^l>>5)?l:46:0;(O&=15)||puts(o))printf("%02x ",l);O>1&&puts(o);}
|
||||
// 115
|
||||
char O,o[20];main(l){for(;O[o]=~(l=getchar())?4<(4^l>>5)?l:46:0;(O=-~O&15)||puts(o))printf("%02x ",l);O&&puts(o);}
|
||||
// 113
|
||||
char O,o[20];main(l){for(;~l;(O=~l?printf("%02x ",l),-~O&15:!O)||puts(o))O[o]=~(l=getchar())?4<(4^l>>5)?l:46:0;}
|
||||
// 112
|
||||
char O,o[20];main(l){for(;~l;(O=~l?-~O&printf("%02x ",l)*5:!O)||puts(o))O[o]=~(l=getchar())?4<(4^l>>5)?l:46:0;}
|
||||
// 111
|
||||
char O,o[20];main(l){for(;~l;O||puts(o))O=(O[o]=~(l=getchar())?4<(4^l>>5)?l:46:0)?-~O&printf("%02x ",l)*5:!O;}
|
||||
// 110
|
||||
char O,o[0];main(l){for(;~l;O||puts(o))O=(O[o]=~(l=getchar())?4<(4^l>>5)?l:46:0)?-~O&printf("%02x ",l)*5:!O;}
|
||||
// 109
|
||||
char O,o[];main(l){for(;~l;O||puts(o))O=(O[o]=~(l=getchar())?4<(4^l>>5)?l:46:0)?-~O&printf("%02x ",l)*5:!O;}
|
||||
</code></pre>
|
||||
|
||||
<p>There are solutions without the ASCII sidebar that are significantly shorter.
|
||||
These do not compete in the same category, since their output is materially different.
|
||||
They are derived from the solutions above, but are still fascinating as concise utilities,
|
||||
so here is their progression, for the curious:</p>
|
||||
|
||||
<pre><code>// 102
|
||||
I;O(O){putchar(O+48+39*(9<O));}main(l){for(;~(l=getchar());O(++I&15?~15:~37))O(l>>4),O(l&15);O(-38);}
|
||||
// 80
|
||||
O;main(l){while(~(l=getchar()))printf("%02x%c",l,++O&15?32:10);O&15&&puts("");}
|
||||
// 78
|
||||
O;main(l){for(;~l;(O=~(l=getchar())?printf("%02x ",l),-~O&15:!O)||puts(""));}
|
||||
// 77
|
||||
O;main(l){for(;~l;(O=~(l=getchar())?-~O&printf("%02x ",l)*5:!O)||puts(""));}
|
||||
// 76
|
||||
O;main(l){for(;~l;O||puts(&O))O=~(l=getchar())?-~O&printf("%02x ",l)*5:!O;}
|
||||
</code></pre>
|
||||
|
||||
<p>It is possible to reduce the size of each of these by one by eliding the trailing newline.
|
||||
This was not reported above since the newline kept getting appended by processing software,
|
||||
and it is more interesting to remove characters by changing code than by filtering:</p>
|
||||
|
||||
<pre><code>$ tr -d '\012' < 109.c | wc -c
|
||||
108
|
||||
$ tr -d '\012' < 76.c | wc -c
|
||||
75
|
||||
$ tr -d '\012' < 109.c | cc -o 108 -xc -
|
||||
$ verify 108
|
||||
$
|
||||
</code></pre>
|
||||
|
||||
<p>An obfuscated hex dump has been done before:
|
||||
<a href="http://ioccc.org/1986/bright/bright.c">1986/bright/bright.c</a> is similar in function,
|
||||
but it uses more characters in just setting up its obfuscation than this entire solution!</p>
|
||||
|
||||
<h2>BIGGER SPOILER</h2>
|
||||
|
||||
<p>If you are unhappy with the way DEL (character 127) is handled,
|
||||
replace the cryptic expression <code>4<(4^l>>5)?l:46</code> with <code>32>l|l>126?46:l</code>.
|
||||
Both take the same number of characters, but the former is a bit more interesting.
|
||||
Bonus question: how does the first expression work?</p>
|
||||
|
||||
<h2>BIGGEST SPOILER (and some history)</h2>
|
||||
|
||||
<p>Technically, <code>char o[0];</code> is illegal (SS 6.7.6.2) according to ISO (N1570).
|
||||
And <code>char o[];</code> is a conditionally supported feature (SS 6.7.6.2, 6.10.8.3).
|
||||
However, it works in modern C implementations as an extension,
|
||||
including GCC, Clang and TCC, for X86 and ARM,
|
||||
on multiple operating systems (Linux, OSX, FreeBSD), so it is <em>functionally</em> correct.
|
||||
MicroSoft Visual C++ does not allow <code>char o[]</code> or <code>char o[0]</code>,
|
||||
and implements its close relative <code>char o[1]</code>
|
||||
such that writing more than a single char will cause a fault, which is <em>technically</em> correct.</p>
|
||||
|
||||
<p>But how does this work at all, even as an extension?
|
||||
<code>o[]</code> allocates one(!) byte in a zero-filled data area (formerly BSS).
|
||||
The UNIX-derived systems this code was run upon all place the
|
||||
storage of <code>O</code> and <code>o</code> into a zero-filled VM page with nothing following:
|
||||
thus, there are plenty of available and unused zero bytes following <code>O</code>, addressed via <code>o</code>,
|
||||
and this code only needs 17.
|
||||
This is <em>undefined</em> behavior, but as shown, it is widely available.</p>
|
||||
|
||||
<p>The <a href="http://minnie.tuhs.org/cgi-bin/utree.pl">1979 Seventh Edition UNIX</a> (v7) system pre-dates the IOCCC by several years,
|
||||
and the source code to <code>sh</code>(1) was a <a href="http://ioccc.org/all/README">significant inspiration for this contest</a>.
|
||||
There are two C compilers present: <code>cc</code> written by Dennis Ritchie, and <code>pcc</code> written by Steven Johnson.
|
||||
The nested conditional expressions in 116 and smaller are too complex for <code>cc</code> (“Illegal conditional”)
|
||||
but <code>pcc</code> handles them correctly, and neither compiler accepts <code>char o[]</code> or <code>char o[0]</code> nor puts the bytes in
|
||||
a zero-filled page (as a paged VM was not yet written for UNIX).</p>
|
||||
|
||||
<p>More significant is that v7 <code>printf</code>(3) does not report the number of characters written,
|
||||
and therefore 111 compiles but does not work correctly;
|
||||
113 is the shortest code that compiles and runs correctly in Ancient UNIX.</p>
|
||||
|
||||
<blockquote><p>Interesting digression: v7 <code>printf</code> (<code>_doprnt</code>) was written in PDP-11 assembler.
|
||||
It pre-dates <code>varargs.h</code>, and assembly was the only way to gain access to the variable argument types.
|
||||
The first edition <em>The C Programming Language</em>, 1978, page 71, remarks:</p>
|
||||
|
||||
<blockquote><p>By the way, there is no entirely satisfactory way to write a portable function
|
||||
that accepts a variable number of arguments, because there is no portable way
|
||||
for the called function to determine how many arguments where actually passed to it in a given call.
|
||||
…
|
||||
<code>printf</code>, the most common C function with a variable number of arguments,
|
||||
… is also non-portable and must be modified for different environments.</p></blockquote>
|
||||
|
||||
<p>It is fascinating to explore the roots of C through the history of the operating system
|
||||
it was birthed within. C is often criticized as a difficult, inscrutable language,
|
||||
but as this contest demonstrates, this is in parody.
|
||||
<em>Shell-gol</em> is one of those instances where someone <a href="http://www.computerworld.com.au/article/279011/a-z_programming_languages_bourne_shell_sh/?pp=4">preferred a different language</a>,
|
||||
and (ab)used the preprocessor to re-mold C into something they found comfortable.
|
||||
Most of the rest of the system, especially in the kernel,
|
||||
are models of clarity and efficient expression.</p></blockquote>
|
||||
|
||||
<h2>TL;DR</h2>
|
||||
|
||||
<p>So which version is the shortest, portable hex dump?</p>
|
||||
|
||||
<ul>
|
||||
<li>109 works with (most?) modern Unix-like systems and compilers, see example list above.</li>
|
||||
<li>111 works adds Microsoft, is standards-approved, and does not exploit undefined behavior.</li>
|
||||
<li>113 works on Ancient UNIX and the portable C compiler.</li>
|
||||
<li>119 works on all platforms, including the original Ritchie PDP-11 C compiler.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Coda</h2>
|
||||
|
||||
<p>Clearly, the smallest possible program violates modern best practice.
|
||||
It is not even possible to compile cleanly, but it will compile correctly.</p>
|
||||
|
||||
<p>Included is <code>prog.nowarn.c</code>, a modern C implementation that is – perhaps – the smallest,
|
||||
clean-compiling version using <code>clang</code> or <code>gcc</code> with <code>-Wall -pedantic</code>.
|
||||
Note that while this is larger than all but the original attempt,
|
||||
it will <em>not</em> work with the original Ritchie PDP-11 C compiler,
|
||||
since the expression within the ternary remains too complex.</p>
|
||||
|
||||
<p>Try</p>
|
||||
|
||||
<pre><code>cat prog.c prog.nowarn.c
|
||||
</code></pre>
|
||||
|
||||
<p>to compare the differences (<code>diff</code> is not helpful on a one-liner).</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<TABLE><TR>
|
||||
<TD><a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/3.0/88x31.png" /></a></TD>
|
||||
<TD><P>© Copyright 1984-2018,
|
||||
<A HREF="/judges.html">Leo Broukhis, Simon Cooper, Landon Curt Noll</A>
|
||||
- All rights reserved<BR>
|
||||
This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
|
||||
<TD> <!--<a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
|
||||
</TR></TABLE>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,428 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="GENERATOR" content="mkd2html 2.1.5a DL=DISCOUNT">
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
|
||||
<link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="../hint.css">
|
||||
<title>Best abuse of the rules</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Best abuse of the rules</h1>
|
||||
|
||||
<p>Dave Burton<br>
|
||||
<a href="http://ioccc.snox.net">http://ioccc.snox.net</a></p>
|
||||
|
||||
<h2>Judges' comments:</h2>
|
||||
|
||||
<h3>To use:</h3>
|
||||
|
||||
<pre><code>make
|
||||
|
||||
./prog [-tcksri] < file.c
|
||||
</code></pre>
|
||||
|
||||
<h3>Try:</h3>
|
||||
|
||||
<pre><code>./prog -i < prog.c
|
||||
./prog -s < prog.c
|
||||
./prog -sk < prog.c
|
||||
</code></pre>
|
||||
|
||||
<p>If you get stuck, try:</p>
|
||||
|
||||
<pre><code>make test
|
||||
</code></pre>
|
||||
|
||||
<p>If you get really stuck, try:</p>
|
||||
|
||||
<pre><code>man ./tac.man
|
||||
</code></pre>
|
||||
|
||||
<h3>Selected Judges Remarks:</h3>
|
||||
|
||||
<p>They say size isn’t everything, and in the case of IOCCC <a href="/2018/iocccsize.c">iocccsize.c</a>
|
||||
that is saying something! What is this program weighing and how much does it weigh?</p>
|
||||
|
||||
<h2>Author’s comments:</h2>
|
||||
|
||||
<h2>tac - tokenize and count C and derivative languages</h2>
|
||||
|
||||
<blockquote><pre style="font-style:italic">
|
||||
tac computes C program size
|
||||
(obfuscated / otherwise)
|
||||
by splitting code as tokens small,
|
||||
ignoring space, then counting all.
|
||||
|
||||
It tries quite hard to act the same
|
||||
as counting tool of I-OCCC fame.
|
||||
Some bugs were fixed, it's faster too,
|
||||
and does more things, just add some glue!
|
||||
|
||||
It does far more than print the size:
|
||||
the token part's a better prize!
|
||||
With each upon on a single line,
|
||||
how many things can you design?
|
||||
|
||||
Included is a keyword sorter,
|
||||
de-obfuscator, freq reporter.
|
||||
With code produced as little parts,
|
||||
just add your own creative arts.
|
||||
|
||||
But first you have to figure out
|
||||
the braces part, without a doubt!
|
||||
And then the code - it isn't easy:
|
||||
for as else? That's rather cheesy!
|
||||
|
||||
The rest of it is standard fare:
|
||||
expressions strange, the globals bare,
|
||||
confusing symbols one and oh,
|
||||
and precedence you have to know.
|
||||
|
||||
The keyword list was made external,
|
||||
because of standards change eternal.
|
||||
Thus other languages can now,
|
||||
be counted just like C, somehow!
|
||||
|
||||
I hope you find this code obscure
|
||||
enough to win, and thus procure
|
||||
a public place for all to see
|
||||
how badly I can butcher C!
|
||||
</pre></blockquote>
|
||||
|
||||
|
||||
<h2>Said another way….</h2>
|
||||
|
||||
<p><code>tac</code> is the inverse of <code>cat</code>(1): it un-concatenates its input into C tokens,
|
||||
writing the token stream to stdout. There are options to suppress the token ids,
|
||||
summarize the token counts, and several options to allow it to be compatible
|
||||
with <code>iocccsize</code>.</p>
|
||||
|
||||
<p>The token-based output is quite useful in analyzing source code (see below),
|
||||
and the counter is more accurate than <code>iocccsize</code> (see below); but this can be
|
||||
fixed by using the -c compatibility flag, restoring the following problems as
|
||||
in the official tool:</p>
|
||||
|
||||
<ul>
|
||||
<li>whitespace <strong>within</strong> a string is <strong>not</strong> counted;
|
||||
this seems wrong, as these chars <strong>are</strong> significant</li>
|
||||
<li>“<code>{;}</code>” is not counted within a double-quoted string</li>
|
||||
<li>whitespace preceding a comment is char-counted, unless the comment starts a line</li>
|
||||
<li>-k processes the reserved words within <code>//</code> comments(!), but not <code>/*</code>, changing the counts</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>The following bugs are always corrected:</p>
|
||||
|
||||
<ul>
|
||||
<li>treats <code>/*/</code> as a complete comment (<code>/*/int if for/*/</code> has three keywords)</li>
|
||||
<li>-k enables <code>//*</code> or within a line comment <code>/*</code> to initiate a comment block until following <code>*/</code></li>
|
||||
<li>-k processes double quote characters in <code>//</code> comments -
|
||||
thus a solitary quote consumes everything until the next quote</li>
|
||||
<li>single quotes are not handled correctly (<code>'"'</code> starts a dquote in <code>iocccsize</code>)</li>
|
||||
<li><code>#ifndef</code> is omitted as a keyword (but <code>#ifdef</code> is allowed?)</li>
|
||||
<li>I is not a reserved word.</li>
|
||||
<li><code>tac</code> correctly penetrates <a href="http://ioccc.org/2014/birken/hint.html" title="Best use of port 1701">23rd century cloaking technology</a>. ;-)</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>There is one (known) remaining problem with detection:</p>
|
||||
|
||||
<ul>
|
||||
<li><p>comments between preprocessor hash and keyword are not replaced with whitespace;
|
||||
the following counts #include as two tokens, <code>#</code> and <code>include</code> (not as a reserved word):</p>
|
||||
|
||||
<pre><code> #/*this will not be counted*/include/*correctly*/<stdio.h>
|
||||
</code></pre></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>Fixing this properly hampers backwards compatibility in counting. This requires
|
||||
eliding comments during readsource (ISO 5.1.1.2, phase 3), and yet still
|
||||
counting words correctly absent -k.</p>
|
||||
|
||||
<h2>Backwards Compatibility</h2>
|
||||
|
||||
<p><code>tac</code> was run over all 366 previous IOCCC winning entries:</p>
|
||||
|
||||
<pre><code>find ~/src/obc -type f -name \*.c | wc
|
||||
</code></pre>
|
||||
|
||||
<p>The discrepancies found are documented and explained in the file “discrepancies”.</p>
|
||||
|
||||
<pre><code>find ~/src/obc -type f -a -name "*.c" | xargs ./spotcheck ./prog | ./spotdiff |
|
||||
grep -v keep | diff -bw - discrep* | grep "[<>] cl "
|
||||
</code></pre>
|
||||
|
||||
<p>In summary, there are only 6 unique entries out of 366 that have any variation
|
||||
in Rule 2 counts; in all cases, the differences are due to bugs within
|
||||
<code>iocccsize</code>, described in detail in the file <code>discrepancies</code>. There are only 40
|
||||
files (40/366, ~11%, including originals and variations) that differ at all, 31
|
||||
only in word count; most word count differences appear related to comment block
|
||||
detection, weighted more towards recent entries (2011 and onward = 20/40 ~50%).</p>
|
||||
|
||||
<p>This (minor) variation in word count values has not been addressed since
|
||||
it is not a qualifying metric, nor is it very useful in a programming context:
|
||||
whitespace surrounds English words, not necessarily C tokens, as in <code>a+=1;</code>.</p>
|
||||
|
||||
<p>Accuracy (versus compatibility) is demonstrated through a series of small test cases
|
||||
designed to allow exhaustive, hand-counted values for comparison with the tool values.
|
||||
These test cases were vital in debugging and regression testing, and provided a way to
|
||||
determine which tool was correct when there were differences.</p>
|
||||
|
||||
<blockquote><p>A version of this tool in more clearly written C (tac.c)
|
||||
is presented for the Judge’s consideration as a more accurate replacement for <code>iocccsize</code>.
|
||||
This obfuscated entry is derived from (and compatible with) that code,
|
||||
but due to obfuscation, has had some significant, deep changes for the contest.
|
||||
Nevertheless, the more clearly written code remains a spoiler for this entry.</p></blockquote>
|
||||
|
||||
<p>NB: <code>iocccsize</code> gets a different answer from <code>tac</code> on its own (iocccsize.c) source code;
|
||||
<code>tac</code> gets the correct answer. This is due to the aforementioned bugs within <code>iocccsize</code>,
|
||||
proved by fixing iocccsize.c with the included patch, so <code>iocccsize</code> reports
|
||||
the correct answer for itself.</p>
|
||||
|
||||
<h2>But wait… There’s More!</h2>
|
||||
|
||||
<p>There is no limit on line length, file length, comment length, or identifier length.</p>
|
||||
|
||||
<p><code>tac</code> features an accurate tokenizer; which presents each C token on a line by itself.
|
||||
This feature enables interesting analyses of C (and C++) code, hard to get any other way.</p>
|
||||
|
||||
<p>For instance, here is a simple token counter, useful in finding repeated long tokens, or operator
|
||||
frequency, or counting the references to identifiers, constants, or breadth of use of the
|
||||
language:</p>
|
||||
|
||||
<pre><code>!/bin/sh
|
||||
cat $* | ./prog -t | sort | uniq -c | sort -k1nr
|
||||
</code></pre>
|
||||
|
||||
<p>And here is a C keyword frequency counter:</p>
|
||||
|
||||
<pre><code>#!/bin/sh
|
||||
function iskeyword {
|
||||
awk 'BEGIN{f="c11";while(getline<f)k[$1]=0}
|
||||
{if($1 in k)k[$1]++}END{for(i in k)print k[i],i}'
|
||||
}
|
||||
cat $* | ./prog -t | iskeyword | sort -k1nr
|
||||
</code></pre>
|
||||
|
||||
<p>This script was used to “optimize” the reserved word order so the most frequent IOCCC
|
||||
winning entry keywords are checked first.</p>
|
||||
|
||||
<blockquote><p>An interesting aside: as might be expected, obfuscation has changed the frequency of
|
||||
keyword distribution over time. The top five for the decades:</p>
|
||||
|
||||
<pre><code> 1980s 1990s 2000s 2010s
|
||||
----- ----- ----- -----
|
||||
94 if 532 char 375 if 254 int
|
||||
69 for 524 if 372 char 217 for
|
||||
59 while 417 int 332 int 198 if
|
||||
48 char 223 for 184 for 121 return
|
||||
43 int 223 void 165 return 104 char
|
||||
</code></pre></blockquote>
|
||||
|
||||
<p>The keyword list is external to the program, and is easily changed, sorted, checked, verified.
|
||||
This allows such additional programs in concert with the tool’s primary operation.</p>
|
||||
|
||||
<p>A poor-man’s de-obfuscator can be based upon the output of <code>tac -t</code> and a handful of
|
||||
simple rules (and another use of the external keyword file).
|
||||
A more refined version of this is included in the file <code>unob.sh</code>,
|
||||
but the simple code below is a serviceable obfuscated C de-obfuscator in a <em>scripting language</em>.
|
||||
It really is this easy with <code>tac</code>:</p>
|
||||
|
||||
<pre><code>#!/bin/sh
|
||||
script='
|
||||
BEGIN {
|
||||
last=nl="\n";
|
||||
f="c11"; while(getline <f > 0) kw[$0]++; close(f);
|
||||
}
|
||||
|
||||
function iskw(a) { return a in kw }
|
||||
function indent(a) { return sprintf("%*s", n*3, " ") }
|
||||
function newline() { if (!infor && last != nl) printf last=nl; }
|
||||
function show(a) {
|
||||
if (last==nl) printf "%s", indent()
|
||||
printf "%s%s", space(), a
|
||||
last=a
|
||||
}
|
||||
function space() {
|
||||
return iskw(last) ||
|
||||
(last ~ /[A-Za-z0-9_+-\/%^[&\]\)=:<>;]$/ && $0 !~ /[:;()\[\],]/) ? " " : ""
|
||||
}
|
||||
|
||||
/^\(/ { ++paren }
|
||||
/^\)/ { --paren }
|
||||
|
||||
/^for/ { newline(); infor=1 }
|
||||
infor && /^;/ { ++infor; show($0 " "); next }
|
||||
infor==1 && /^:/ { ++infor }
|
||||
infor>1 && paren==0 { infor=0 }
|
||||
|
||||
/^\?/ { tern++; n++; newline(); show($0 " "); next }
|
||||
tern && /^:/ { newline(); show($0); --tern; --n; next }
|
||||
|
||||
/^#/ { newline(); show($0); newline(); next }
|
||||
/^;/ { show($0); newline(); next }
|
||||
/^{/ { show($0); ++n; newline(); next }
|
||||
/^}/ { n--; newline(); show($0); newline(); next }
|
||||
|
||||
{ show($0) }
|
||||
'
|
||||
cat $* | sed 's/#include/##include/' | cpp -E -trigraphs |
|
||||
sed 's/^# .*$//' | sed 's/^#//' |
|
||||
./prog -t | awk "$script"
|
||||
</code></pre>
|
||||
|
||||
<h2>On the question of obfuscation</h2>
|
||||
|
||||
<ul>
|
||||
<li><p>I assume you noticed the <a href="https://www.youtube.com/watch?v=fUspLVStPbk&start=53" title="Meaning of Life">braces</a>?</p>
|
||||
|
||||
<p><em>Every brace is sacred,<br>
|
||||
Every brace is great.<br>
|
||||
If a brace is wasted,<br>
|
||||
Clang gets quite irate</em>.</p></li>
|
||||
<li><p>Keywords follow the 2010s top five, without the <code>if</code>, for interesting flow control.</p></li>
|
||||
<li>Sometimes a <code>for</code> can be an <code>else</code> - <a href="https://www.youtube.com/watch?v=OHVjs4aobqs" title="Inconceivable">inconceivable</a>!</li>
|
||||
<li>I see the <code>getopt</code>. But “<a href="https://www.youtube.com/watch?v=Ug75diEyiA0" title="Where's the beef?">where’s the beef?</a>”</li>
|
||||
<li><p>No character constants, several int constants, and one string
|
||||
(hint: which does not encode letters) – how does this code parse code?</p>
|
||||
|
||||
<blockquote><p>Interesting aside: how many is “several int constants”?</p>
|
||||
|
||||
<pre><code> ./prog < prog.c 2>/dev/null | awk '$1~/260/{a[$2]++}END{for(i in a)print i,a[i]}'
|
||||
... | wc
|
||||
</code></pre>
|
||||
|
||||
<p>Which numbers are most often used?</p>
|
||||
|
||||
<pre><code> ... | sort -k2nr | sed 5q
|
||||
</code></pre></blockquote></li>
|
||||
<li><p>The code describes its function by careful arrangement of variables up front…</p></li>
|
||||
<li>…coupled with a description of the typical IOCCC contestant, or at least the author</li>
|
||||
<li>Why shouldn’t trigraph parsing be written in trigraph?</li>
|
||||
<li>Where iocccsize.c mocks, this code flaunts:
|
||||
“<em>no matter how well you may think you understand this code, you don’t, so don’t mess with it. :-)</em>”</li>
|
||||
<li><code>O,0,l,1</code> are used to confusing effect, local names obscure global names.</li>
|
||||
<li>Globals are used to pass information between routines: don’t reorder “unrelated” statements….</li>
|
||||
<li>How does the compatibility mode account for the fundamentally different manner of computation?</li>
|
||||
<li>The algorithm is quite efficient; reserved word detection and trigraph parsing particularly so.</li>
|
||||
<li>This may be the first obfuscated submission that provides the means for its own de-obfuscation.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Rule 2</h2>
|
||||
|
||||
<p>The keyword list is externalized as an include file. This presents a useful
|
||||
feature for the source code: not only can the reserved word script above be
|
||||
produced, but the tool can be rebuilt with any set of reserved words, just by
|
||||
using a different list. For instance: removing all the secondary keywords;
|
||||
removing all the C11 keywords; trying just K&R C. Since C++ and Java share the
|
||||
same operators as C, just change the keyword list and <code>tac</code> will correctly
|
||||
tokenize both of these; the tokens >>> and :: can be handled with a short
|
||||
post-filter (tokenfix, included).</p>
|
||||
|
||||
<p>I believe this entry may also satisfy the request for gratuitous use of all the C11 keywords?
|
||||
Whether this context satisfies “intended C language context” is a matter of interpretation. ;-)
|
||||
And <code>tac</code> is ready for the IOCCC++ contest. And the IOJCC trashcan.</p>
|
||||
|
||||
<p>The following reserved word files are included:</p>
|
||||
|
||||
<pre><code>kandr from my venerable 1978 18th printing "The C Programming Language"
|
||||
v7unix 7th edition Unix source code, extracted from c00.c
|
||||
kandr2 from my 1988 1st printing "The C Programming Language", 2e
|
||||
ansi ANS X3.159-1989
|
||||
c99 ISO/IEC 9899:1999(E)
|
||||
c11 ISO/IEC 9899:201x(E) N1570
|
||||
c++98 http://en.cppreference.com/w/cpp/keyword
|
||||
c++11 ISO/IEC 14882:2011(E) N3337 2012-01-16
|
||||
c++14 ISO/IEC 14882:2014(E) N4296 2014-11-09
|
||||
java8 http://docs.oracle.com/javase/specs/index.html
|
||||
ioccc.kw.freq c11 + additional words, sorted on frequency of occurrence in ioccc winners
|
||||
</code></pre>
|
||||
|
||||
<p>NB: The keyword file used in this code is derived from the list in iocccsize.c,
|
||||
which is neither complete (<code>#define</code>, <code>#ifndef</code>, <code>#undef</code> are missing
|
||||
– yes, Virginia knows about <code>#define</code> omitted on purpose),
|
||||
nor correct (many more are added: <code>I</code>, <code>true</code>, <code>bool</code>, <code>compl</code>, …):</p>
|
||||
|
||||
<pre><code>(sed -n '1p' c11; sed -n '2,$p' ioccc.kw.freq | sort) | comm -3 - c11
|
||||
</code></pre>
|
||||
|
||||
<p>That is an obfuscated way to say “diff”. But it also more clearly shows the, um, diffs.</p>
|
||||
|
||||
<p>The usage string is similarly externalized, providing a better usability string than
|
||||
the limits would otherwise allow. If this is considered bending the rules too far,
|
||||
just -DU=O to get a passible, if cryptic, usage message using no additional octets
|
||||
than without the define.
|
||||
This also allows the builder to configure the amount of help a utility should provide
|
||||
(<a href="https://www.youtube.com/watch?v=VU0GYSA1POs" title="Ants">you want a manpage? Because that’s how you get a manpage.</a>)
|
||||
– a rather significant point of contention made moot.</p>
|
||||
|
||||
<p>There is definitely abuse of the Rule2 counter, exploiting a “feature” of <code>iocccsize</code>:
|
||||
<code>iocccsize</code> does not Rule2 count {, } and ; when followed by whitespace – even within a string!
|
||||
Thus: Freecode, a simple, uncounted, highly obfuscated encoding of a central part
|
||||
of this program. (The reserved word list is not Freecoded, both because it is useful
|
||||
apart from the program, and because Freecode is not entirely free.*)</p>
|
||||
|
||||
<ul>
|
||||
<li>Some restrictions apply. Not approved for all uses. Some assembly required.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Compilation</h2>
|
||||
|
||||
<p>The code is ANSI compliant, but it does have a string longer than 509 characters.
|
||||
It has been tested on OSX and Linux, Clang and GCC.</p>
|
||||
|
||||
<p>The code uses trigraphs, ironically: it parses trigraphs with trigraph code.
|
||||
Because that’s funny. And it remains obscure after, so trigraphs are not used for obfuscation.
|
||||
Thus -trigraphs -Wno-trigraphs (which is also humorous).</p>
|
||||
|
||||
<p>It’s obfuscated C. Thus -Wno-parentheses -Wno-empty-body -Wno-char-subscripts.</p>
|
||||
|
||||
<p>The code uses unsigned chars, but C strings are signed. Thus -Wno-pointer-sign.
|
||||
NB: This is <em>not</em> a portability concern, the one string holds only printable ASCII characters.</p>
|
||||
|
||||
<p>Thus:</p>
|
||||
|
||||
<pre><code>clang -ansi -Wall -trigraphs -Wno-trigraphs -Wno-parentheses -Wno-empty-body -Wno-char-subscripts -Wno-pointer-sign -DU=O -DW=\"keywords\" -o prog prog.c
|
||||
</code></pre>
|
||||
|
||||
<h2>Coda</h2>
|
||||
|
||||
<p>Cody Ferguson was relentless in his pursuit of bugs.
|
||||
Thanks to his reports, the version of <code>unob.sh</code> is stronger,
|
||||
<code>tac</code> groks digraphs, <code>tokenfix</code> corrects for missing digraphs in <code>prog.c</code>,
|
||||
and the program <code>manpage</code> was added to the corpus.</p>
|
||||
|
||||
<p><code>manpage</code> is a useful program that turns ASCII versions of man pages (e.g. <code>tac.man</code>) into real
|
||||
man pages. It works for C and C-like languages, command lines,
|
||||
and was designed to handle man page sections 1-8.
|
||||
It works well on most inputs, but tends to need some raw nroff for more fancy constructions,
|
||||
such as combined arguments
|
||||
(e.g. the -r and -s arguments to tac are not recognised when written as -rs in prose).</p>
|
||||
|
||||
<p>Try:</p>
|
||||
|
||||
<pre><code>manpage tac
|
||||
|
||||
manpage -h
|
||||
manpage -h | manpage
|
||||
manpage -h | manpage -R | less
|
||||
manpage -h | manpage -P | lpr
|
||||
</code></pre>
|
||||
|
||||
<hr />
|
||||
|
||||
<TABLE><TR>
|
||||
<TD><a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/3.0/88x31.png" /></a></TD>
|
||||
<TD><P>© Copyright 1984-2018,
|
||||
<A HREF="/judges.html">Leo Broukhis, Simon Cooper, Landon Curt Noll</A>
|
||||
- All rights reserved<BR>
|
||||
This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
|
||||
<TD> <!--<a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
|
||||
</TR></TABLE>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,308 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="GENERATOR" content="mkd2html 2.1.5a DL=DISCOUNT">
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
|
||||
<link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="../hint.css">
|
||||
<title>Most likely to be awarded</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Most likely to be awarded</h1>
|
||||
|
||||
<p>Marcin Ciura <a href="mailto:mciura@gmail.com">mciura@gmail.com</a><br>
|
||||
Twitter: @mciura</p>
|
||||
|
||||
<h2>Judges' comments:</h2>
|
||||
|
||||
<h3>To use:</h3>
|
||||
|
||||
<pre><code>make
|
||||
|
||||
./prog < text
|
||||
</code></pre>
|
||||
|
||||
<h3>Try:</h3>
|
||||
|
||||
<pre><code>./prog < Makefile
|
||||
./prog < hint.text
|
||||
</code></pre>
|
||||
|
||||
<h3>Selected Judges Remarks:</h3>
|
||||
|
||||
<p>This text was processed by prog. You may get confused.
|
||||
We’re not really sure: prog.c wasn’t commented.
|
||||
Who has been thoroughly puzzled by prog? Also how obfuscated is prog?
|
||||
Having been written in C, how large of a vocabulary has it?</p>
|
||||
|
||||
<h2>Author’s comments:</h2>
|
||||
|
||||
<h1>The Program</h1>
|
||||
|
||||
<p>“The Elements of Style” by prof. William Strunk, Jr. and E. B. White
|
||||
is well known for its dislike of the passive voice. Direct, vigorous,
|
||||
active constructions were instead recommended by the authors.
|
||||
The development of this program has been driven by this tenet.</p>
|
||||
|
||||
<p>Only passive sentences from the standard input are output. The offending
|
||||
part(s) of each sentence will be highlighted. Several kinds of passive
|
||||
constructions are recognized:</p>
|
||||
|
||||
<ul>
|
||||
<li>Plain passive voice.
|
||||
Foo was bazzed by bar.</li>
|
||||
<li>Passive voice with “get”.
|
||||
I got almost quuxed.</li>
|
||||
<li>Contractions.
|
||||
I’m not really quuxed: foo wasn’t bazzed.</li>
|
||||
<li>Questions.
|
||||
Who has been quuxed? Was foo indeed bazzed? How was it bazzed?</li>
|
||||
<li>Clause-initial inversion.
|
||||
Also bazzed is bar.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>Sentences are never broken by periods that follow abbreviations and
|
||||
initials. Both regular and irregular past participles are properly
|
||||
dealt with. Note that some words are red herrings: even though their
|
||||
ending is -ed, they are not past participles.</p>
|
||||
|
||||
<h1>The Big String</h1>
|
||||
|
||||
<p>Here is the purpose of every byte inside the <strong><code>c[]</code></strong> string:</p>
|
||||
|
||||
<ul>
|
||||
<li>0-9: highlighting passive constructions in the output;</li>
|
||||
<li>10-50: classifying characters - called by <strong><code>V(4)</code></strong>;</li>
|
||||
<li>52: outputting the newline character;</li>
|
||||
<li>51-187: tokenizing text and detecting passive constructions - two
|
||||
type A state machines, called by <strong><code>V(2)</code></strong> and <strong><code>V(3)</code></strong>;</li>
|
||||
<li>186-2786: determining word categories (past participles, present
|
||||
simple and past simple forms of “to be”, other forms of “to be”,
|
||||
adverbs, wh-words, and other words) and recognizing abbreviations -
|
||||
two type B state machines, called by <strong><code>V(808)</code></strong> and <strong><code>V(205)</code></strong>.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h1>The State Machines</h1>
|
||||
|
||||
<p>I heard you don’t like state machines so I put a state machine in your
|
||||
state machine so you can reject this entry while you reject this entry.</p>
|
||||
|
||||
<p>Both types of state machines in the program are Mealy machines: we can
|
||||
think of their transitions as triples (<strong><code>transition_label</code></strong>,
|
||||
<strong><code>next_state</code></strong>, <strong><code>output</code></strong>).</p>
|
||||
|
||||
<h2>Type A</h2>
|
||||
|
||||
<p>A state of type A state machine consists of eight transitions whose
|
||||
representations occupy consecutive bytes. The byte
|
||||
<strong><code>c[3 + 8*state + transition_label]</code></strong> contains
|
||||
<strong><code>(unsigned char)(30 + 5*next_state + output)</code></strong>.</p>
|
||||
|
||||
<p>The <code>transition_label</code> is either one of character classes:</p>
|
||||
|
||||
<ul>
|
||||
<li><strong><code>nil</code></strong> = 0,</li>
|
||||
<li><strong><code>space</code></strong> = 1,</li>
|
||||
<li><strong><code>new_line</code></strong> = 2,</li>
|
||||
<li><strong><code>uppercase</code></strong> = 3,</li>
|
||||
<li><strong><code>lowercase</code></strong> = 4,</li>
|
||||
<li><strong><code>period</code></strong> = 5,</li>
|
||||
<li><strong><code>bang_question</code></strong> = 6,</li>
|
||||
<li><strong><code>punctuation</code></strong> = 7,</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>or one of word classes:</p>
|
||||
|
||||
<ul>
|
||||
<li><strong><code>adverb</code></strong> = 0,</li>
|
||||
<li><strong><code>other</code></strong> = 2,</li>
|
||||
<li><strong><code>past_participle</code></strong> = 3,</li>
|
||||
<li><strong><code>to_be</code></strong> = 4,</li>
|
||||
<li><strong><code>are_were</code></strong> = 5,</li>
|
||||
<li><strong><code>wh_word</code></strong> = 6 (cf. the <strong><code>output</code></strong> of type B state machines).</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>The <strong><code>output</code></strong> is either one of:</p>
|
||||
|
||||
<ul>
|
||||
<li><strong><code>end_of_text</code></strong> = 0,</li>
|
||||
<li><strong><code>sentence_start</code></strong> = 1,</li>
|
||||
<li><strong><code>sentence_end</code></strong> = 2,</li>
|
||||
<li><strong><code>token_end</code></strong> = 3,</li>
|
||||
<li><strong><code>ignore</code></strong> = 4,</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>or one of</p>
|
||||
|
||||
<ul>
|
||||
<li><strong><code>passive_construction_start</code></strong> = 1,</li>
|
||||
<li><strong><code>ignore</code></strong> = 2,</li>
|
||||
<li><strong><code>passive_construction_end</code></strong> = 3.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>Type A state machines run continuously. Their state is kept in
|
||||
<strong><code>k[2]</code></strong> and <strong><code>k[3]</code></strong>.</p>
|
||||
|
||||
<p>Below are sample steps of scanning a sequence of characters with
|
||||
classes <strong><code>uppercase</code></strong>, <strong><code>lowercase</code></strong>, <strong><code>period</code></strong>, <strong><code>space</code></strong>,
|
||||
and <strong><code>uppercase</code></strong>.</p>
|
||||
|
||||
<ul>
|
||||
<li><strong><code>state</code></strong> = 7, <strong><code>transition_label</code></strong> = 3 (<strong><code>uppercase</code></strong>), <strong><code>output</code></strong> = <strong><code>sentence_start</code></strong></li>
|
||||
<li><strong><code>state</code></strong> = 14, <strong><code>transition_label</code></strong> = 4 (<strong><code>lowercase</code></strong>), <strong><code>output</code></strong> = <strong><code>ignore</code></strong></li>
|
||||
<li><strong><code>state</code></strong> = 15, <strong><code>transition_label</code></strong> = 5 (<strong><code>period</code></strong>), <strong><code>output</code></strong> = <strong><code>token_end</code></strong></li>
|
||||
<li><strong><code>state</code></strong> = 13, <strong><code>transition_label</code></strong> = 1 (<strong><code>space</code></strong>), <strong><code>output</code></strong> = <strong><code>token_end</code></strong></li>
|
||||
<li><strong><code>state</code></strong> = 18, <strong><code>transition_label</code></strong> = 3 (<strong><code>uppercase</code></strong>), <strong><code>output</code></strong> = <strong><code>sentence_end</code></strong></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>And here are sample steps of scanning tokens with classes <strong><code>to_be</code></strong>,
|
||||
<strong><code>adverb</code></strong>, <strong><code>past_participle</code></strong>.</p>
|
||||
|
||||
<ul>
|
||||
<li><strong><code>state</code></strong> = 8, <strong><code>transition_label</code></strong> = 4 (<strong><code>to_be</code></strong>), <strong><code>output</code></strong> = <strong><code>passive_construction_start</code></strong></li>
|
||||
<li><strong><code>state</code></strong> = 22, <strong><code>transition_label</code></strong> = 0 (<strong><code>adverb</code></strong>), <strong><code>output</code></strong> = <strong><code>ignore</code></strong></li>
|
||||
<li><strong><code>state</code></strong> = 22, <strong><code>transition_label</code></strong> = 3 (<strong><code>past_participle</code></strong>), <strong><code>output</code></strong> = <strong><code>passive_construction_end</code></strong></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Type B</h2>
|
||||
|
||||
<p>Type B state machines are built by a variant of the algorithm described
|
||||
in the paper
|
||||
<em><a href="http://sun.aei.polsl.pl/~mciura/publikacje/lexicon.pdf">How to squeeze a lexicon</a></em>.
|
||||
Their states are represented as interlaced sparse arrays of transitions.</p>
|
||||
|
||||
<p>The <strong><code>transition_label</code></strong> is one of:</p>
|
||||
|
||||
<ul>
|
||||
<li><strong><code>word_start</code></strong> = 0,</li>
|
||||
<li><strong><code>period_or_apostrophe</code></strong> = 1,</li>
|
||||
<li><strong><code>a_z_letter</code></strong> = 2..27.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>The <code>output</code> is either one of word classes:</p>
|
||||
|
||||
<ul>
|
||||
<li><strong><code>adverb</code></strong> = 0,</li>
|
||||
<li><strong><code>ignore</code></strong> = 1,</li>
|
||||
<li><strong><code>other</code></strong> = 2,</li>
|
||||
<li><strong><code>past_participle</code></strong> = 3,</li>
|
||||
<li><strong><code>to_be</code></strong> = 4,</li>
|
||||
<li><strong><code>are_were</code></strong> = 5,</li>
|
||||
<li><strong><code>wh_word</code></strong> = 6,</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>or</p>
|
||||
|
||||
<ul>
|
||||
<li><strong><code>ignore</code></strong> = 1,</li>
|
||||
<li><strong><code>abbreviation</code></strong> = 2.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>The byte <strong><code>c[186 + (state + transition_label)] = (unsigned char)(2 + transition_label + 28 * output)</code></strong>.</p>
|
||||
|
||||
<p>The byte <strong><code>c[836 + 2*(state + transition_label)] =</code></strong></p>
|
||||
|
||||
<ul>
|
||||
<li><strong><code>' '</code></strong> when <strong><code>next_state / 376 == 0</code></strong>,</li>
|
||||
<li><strong><code>';'</code></strong> when <strong><code>next_state / 376 == 1</code></strong>.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>The byte <strong><code>c[837 + 2*(state + transition_label)] =</code></strong></p>
|
||||
|
||||
<ul>
|
||||
<li><strong><code>' '</code></strong> when <strong><code>next_state / 94 % 4 == 0</code></strong>,</li>
|
||||
<li><strong><code>';'</code></strong> when <strong><code>next_state / 94 % 4 == 1</code></strong>,</li>
|
||||
<li><strong><code>'{'</code></strong> when <strong><code>next_state / 94 % 4 == 2</code></strong>,</li>
|
||||
<li><strong><code>'}'</code></strong> when <strong><code>next_state / 94 % 4 == 3</code></strong>.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>The byte <strong><code>c[2136 + (state + transition_label)] = (unsigned char)(32 + next_state % 94)</code></strong>.</p>
|
||||
|
||||
<p>A type B state machine starts in a given <strong><code>state</code></strong> with <strong><code>output</code></strong>
|
||||
set to <strong><code>ignore</code></strong>. It scans a word backwards, converting character by
|
||||
character to <strong><code>transition_label</code></strong>. When it meets <strong><code>word_start</code></strong>, it
|
||||
returns, leaving the most recently stored <strong><code>output</code></strong> in <strong><code>v</code></strong>.
|
||||
It also returns when
|
||||
<strong><code>c[186 + (state + transition_label)] != (unsigned char)(2 + transition_label + 28 * output)</code></strong>,
|
||||
i.e. when the <strong><code>transition_label</code></strong> in the byte mismatches the
|
||||
<strong><code>transition_label</code></strong> used to compute the index. Otherwise, if the
|
||||
<strong><code>output</code></strong> in this byte differs from <strong><code>ignore</code></strong>, the state machine
|
||||
stores it in <strong><code>v</code></strong>. Regardless of the value of the <strong><code>output</code></strong>,
|
||||
it also assigns <strong><code>next_state</code></strong> to <strong><code>state</code></strong> and proceeds to scan
|
||||
the previous character. The state machine that determines the word
|
||||
class is set up so that it never returns <strong><code>ignore</code></strong>.</p>
|
||||
|
||||
<p>Below are sample steps of scanning the word “chiefly”.</p>
|
||||
|
||||
<ul>
|
||||
<li><strong><code>state</code></strong> = 623, <strong><code>transition_label</code></strong> = 26 (‘y’), <strong><code>output</code></strong> = <strong><code>other</code></strong></li>
|
||||
<li><strong><code>state</code></strong> = 602, <strong><code>transition_label</code></strong> = 13 (‘l’), <strong><code>output</code></strong> = <strong><code>adverb</code></strong></li>
|
||||
<li><strong><code>state</code></strong> = 594, <strong><code>transition_label</code></strong> = 7 (‘f’), <strong><code>output</code></strong> = <strong><code>other</code></strong></li>
|
||||
<li><strong><code>state</code></strong> = 549, <strong><code>transition_label</code></strong> = 6 (‘e’), <strong><code>output</code></strong> = <strong><code>ignore</code></strong></li>
|
||||
<li><strong><code>state</code></strong> = 543, <strong><code>transition_label</code></strong> = 10 (‘i’), <strong><code>output</code></strong> = <strong><code>adverb</code></strong></li>
|
||||
<li><strong><code>state</code></strong> = 0, <strong><code>transition_label</code></strong> = 9 (‘h’) mismatches the value stored
|
||||
in the byte. Return <strong><code>adverb</code></strong>.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>And here are sample steps of scanning the string “i.e.”:</p>
|
||||
|
||||
<ul>
|
||||
<li><strong><code>state</code></strong> = 19, <strong><code>transition_label</code></strong> = 1 (‘.’), <strong><code>output</code></strong> = <strong><code>ignore</code></strong></li>
|
||||
<li><strong><code>state</code></strong> = 24, <strong><code>transition_label</code></strong> = 6 (‘e’), <strong><code>output</code></strong> = <strong><code>ignore</code></strong></li>
|
||||
<li><strong><code>state</code></strong> = 3, <strong><code>transition_label</code></strong> = 1 (‘.’), <strong><code>output</code></strong> = <strong><code>ignore</code></strong></li>
|
||||
<li><strong><code>state</code></strong> = 2, <strong><code>transition_label</code></strong> = 10 (‘i’), <strong><code>output</code></strong> = <strong><code>ignore</code></strong></li>
|
||||
<li><strong><code>state</code></strong> = 1, <strong><code>transition_label</code></strong> = 0 (‘\0’), <strong><code>output</code></strong> = <strong><code>abbreviation</code></strong>.
|
||||
Return <strong><code>abbreviation</code></strong>.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h1>Remarks</h1>
|
||||
|
||||
<p>The judges found a bug in the handling of contractions: <strong><code>prog.orig.c</code></strong>
|
||||
outputs “foo wasn'<strong>[t bazzed]</strong>”. I fixed the bug in <strong><code>prog.c</code></strong>, making
|
||||
it output “foo <strong>[wasn’t bazzed]</strong>” instead, and took the liberty to merge
|
||||
one statement into a <strong><code>for</code></strong> loop inside its <strong><code>main()</code></strong> function.</p>
|
||||
|
||||
<p>The program uses a 9,437,187-byte buffer so it probably will not run
|
||||
on 16-bit and smaller machines without changing the size of array <strong><code>C[]</code></strong>
|
||||
and the expression <strong><code>9<<20</code></strong> inside the call to <strong><code>read()</code></strong>.</p>
|
||||
|
||||
<p>I have tested it on:</p>
|
||||
|
||||
<ul>
|
||||
<li>Linux with gcc version 5.4.0 20160609,</li>
|
||||
<li>Linux with clang version 3.4-1ubuntu3,</li>
|
||||
<li>OS/X with Apple LLVM version 6.0 (clang-600.0.57).</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>For a clean compile under c89 and c90, add <strong><code>-Woverlength-strings</code></strong>
|
||||
to <strong><code>CSILENCE</code></strong>.</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<TABLE><TR>
|
||||
<TD><a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/3.0/88x31.png" /></a></TD>
|
||||
<TD><P>© Copyright 1984-2018,
|
||||
<A HREF="/judges.html">Leo Broukhis, Simon Cooper, Landon Curt Noll</A>
|
||||
- All rights reserved<BR>
|
||||
This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
|
||||
<TD> <!--<a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
|
||||
</TR></TABLE>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,78 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="GENERATOR" content="mkd2html 2.1.5a DL=DISCOUNT">
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
|
||||
<link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="../hint.css">
|
||||
<title>Best tool to reveal holes</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Best tool to reveal holes</h1>
|
||||
|
||||
<p>Yusuke Endoh<br>
|
||||
Twitter: @mametter</p>
|
||||
|
||||
<h2>Judges' comments:</h2>
|
||||
|
||||
<h3>To use:</h3>
|
||||
|
||||
<pre><code>make
|
||||
./prog < textfile > output.gif
|
||||
</code></pre>
|
||||
|
||||
<h3>Try:</h3>
|
||||
|
||||
<pre><code>./prog < golem.txt > golem.gif
|
||||
./prog < smily.txt > smily.gif
|
||||
</code></pre>
|
||||
|
||||
<h3>Selected Judges Remarks:</h3>
|
||||
|
||||
<p>To get the best experience, use a GIF viewer that can handle animated gifs.
|
||||
On OS X you can use Safari using “open -a Safari smily.gif”</p>
|
||||
|
||||
<p>Some things to consider are that this 2.5KiB gem encodes a 96 character 8x8
|
||||
font (naively this could already take 6144 bytes) and a GIF encoder. But
|
||||
how does it know which characters are closed?</p>
|
||||
|
||||
<p>You should only give this program printable ASCII characters.</p>
|
||||
|
||||
<p>Unfortunately this won’t run on your PDP8, if you had one, as it needs at
|
||||
least 2MiB of memory to run in.</p>
|
||||
|
||||
<h2>Author’s comments:</h2>
|
||||
|
||||
<p>This program generates an animated GIF from a plain text. Run:</p>
|
||||
|
||||
<pre><code>gcc -o prog prog.c
|
||||
./prog < invisible.txt > invisible.gif
|
||||
</code></pre>
|
||||
|
||||
<p>Open invisible.gif and then wait a minute. You will see a hidden message.
|
||||
Can you tell the difference between letters that leaves the mark and ones that does not?</p>
|
||||
|
||||
<p>Other examples:</p>
|
||||
|
||||
<pre><code>./prog < golem.txt > golem.gif
|
||||
./prog < smily.txt > smily.gif
|
||||
</code></pre>
|
||||
|
||||
<p>The program itself has a hidden message.</p>
|
||||
|
||||
<pre><code>./prog < prog.c > prog.gif
|
||||
</code></pre>
|
||||
|
||||
<hr />
|
||||
|
||||
<TABLE><TR>
|
||||
<TD><a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/3.0/88x31.png" /></a></TD>
|
||||
<TD><P>© Copyright 1984-2018,
|
||||
<A HREF="/judges.html">Leo Broukhis, Simon Cooper, Landon Curt Noll</A>
|
||||
- All rights reserved<BR>
|
||||
This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
|
||||
<TD> <!--<a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
|
||||
</TR></TABLE>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,80 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="GENERATOR" content="mkd2html 2.1.5a DL=DISCOUNT">
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
|
||||
<link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="../hint.css">
|
||||
<title>Best use of python</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Best use of python</h1>
|
||||
|
||||
<p>Yusuke Endoh<br>
|
||||
Twitter: @mametter</p>
|
||||
|
||||
<h2>Judges' comments:</h2>
|
||||
|
||||
<h3>To use:</h3>
|
||||
|
||||
<pre><code>make
|
||||
|
||||
./prog
|
||||
</code></pre>
|
||||
|
||||
<h3>Try:</h3>
|
||||
|
||||
<pre><code>make
|
||||
|
||||
./prog | tee prog_next.c
|
||||
make prog_next
|
||||
./prog_next | tee prog_next.c
|
||||
make prog_next
|
||||
./prog_next | tee prog_next.c
|
||||
|
||||
make python
|
||||
|
||||
make python3
|
||||
</code></pre>
|
||||
|
||||
<h3>Selected Judges Remarks:</h3>
|
||||
|
||||
<p>And now for something completely different: A program whose metabolic
|
||||
processes are a matter of interest only to historians. It has kicked the bucket
|
||||
and departed to that mysterious country from whose bourne no traveller returns!
|
||||
This is an EX-tremely obfuscated program!</p>
|
||||
|
||||
<h2>Author’s comments:</h2>
|
||||
|
||||
<pre><code> ___-----__
|
||||
_-- --__
|
||||
_- _--_ \
|
||||
_- /\ +-.:.:-+ /\ \
|
||||
/ \/ |.:.:.:| \/ |
|
||||
/ |:.:.:.| |
|
||||
/ |.:.:.:| | ___-----___
|
||||
| |.:.:| | / \
|
||||
| |:.:.| | < It's ... |
|
||||
\ |:.| | \ /
|
||||
\ || | ---_____---
|
||||
_--\ |
|
||||
_- -__ |
|
||||
__- --___ |
|
||||
_- |
|
||||
/ |
|
||||
| |
|
||||
</code></pre>
|
||||
|
||||
<hr />
|
||||
|
||||
<TABLE><TR>
|
||||
<TD><a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/3.0/88x31.png" /></a></TD>
|
||||
<TD><P>© Copyright 1984-2018,
|
||||
<A HREF="/judges.html">Leo Broukhis, Simon Cooper, Landon Curt Noll</A>
|
||||
- All rights reserved<BR>
|
||||
This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
|
||||
<TD> <!--<a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
|
||||
</TR></TABLE>
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,80 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="GENERATOR" content="mkd2html 2.1.5a DL=DISCOUNT">
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
|
||||
<link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="../hint.css">
|
||||
<title>Most unstable</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Most unstable</h1>
|
||||
|
||||
<p>Edward Giles</p>
|
||||
|
||||
<h2>Judges' comments:</h2>
|
||||
|
||||
<h3>To use:</h3>
|
||||
|
||||
<pre><code>sudo apt install libsdl2-dev # Linux
|
||||
Something else # MacOS
|
||||
make
|
||||
./prog
|
||||
</code></pre>
|
||||
|
||||
<h3>Try:</h3>
|
||||
|
||||
<pre><code>./prog ioccc.txt
|
||||
./prog prog.c
|
||||
</code></pre>
|
||||
|
||||
<h3>Selected Judges Remarks:</h3>
|
||||
|
||||
<p>Can you explain the behavior of the program when ioccc.txt is given to it as input?</p>
|
||||
|
||||
<p>How would the description of the state machine look like when translated from
|
||||
Polynomish to English?</p>
|
||||
|
||||
<h2>Author’s comments:</h2>
|
||||
|
||||
<h1>Remarks</h1>
|
||||
|
||||
<p>This entry graphically displays a simulation of sand falling.
|
||||
It uses SDL to draw the interface.</p>
|
||||
|
||||
<p>The code makes the following assumptions about the underlying system:</p>
|
||||
|
||||
<ul>
|
||||
<li>SDL 2 is installed from https://libsdl.org</li>
|
||||
<li>“double” is an IEEE 754 floating-point type and sizeof(double)==8</li>
|
||||
<li>The compiler supports the C99 standard</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>In order to simulate the motion of the sand, a cellular automaton is used. The
|
||||
state transition table is not stored directly. Instead, the program stores the
|
||||
coefficients of a polynomial that map each state to the correct one. These
|
||||
coefficients are stored as raw hexadecimal in the V[] array, and they are
|
||||
reinterpreted as doubles when used. This allows more numeric precision in fewer
|
||||
characters (base 16 > base 10), and makes the purpose of the array less clear.</p>
|
||||
|
||||
<p>The code is laid out graphically as a bucket pouring sand, and it is far easier
|
||||
to observe this high-level layout than the code’s actual function.</p>
|
||||
|
||||
<p>The preprocessor is used to both obfuscate the code as a whole and abbreviate
|
||||
the calls to SDL. Additionally, throughout the code, the variables were named
|
||||
so that they are short and easily confused with each other.</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<TABLE><TR>
|
||||
<TD><a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/3.0/88x31.png" /></a></TD>
|
||||
<TD><P>© Copyright 1984-2018,
|
||||
<A HREF="/judges.html">Leo Broukhis, Simon Cooper, Landon Curt Noll</A>
|
||||
- All rights reserved<BR>
|
||||
This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
|
||||
<TD> <!--<a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
|
||||
</TR></TABLE>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,64 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="GENERATOR" content="mkd2html 2.1.5a DL=DISCOUNT">
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
|
||||
<link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="../hint.css">
|
||||
<title>Most likely to top the charts</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Most likely to top the charts</h1>
|
||||
|
||||
<p>Qiming HOU</p>
|
||||
|
||||
<h2>Judges' comments:</h2>
|
||||
|
||||
<h3>To use:</h3>
|
||||
|
||||
<pre><code>make
|
||||
./prog < input.json > output.html
|
||||
</code></pre>
|
||||
|
||||
<p>View <code>output.html</code> in a browser.</p>
|
||||
|
||||
<h3>Try:</h3>
|
||||
|
||||
<pre><code>grep -e '[-?+*/^&|.<>=]' prog.c
|
||||
|
||||
(cd ..; ls -lS */prog.c) | \
|
||||
awk 'BEGIN { print "["; } { print "{\"winner\":\"",$9,"\", \"size\":",$5,"},"} END { print "]"}' \
|
||||
> ioccc.json
|
||||
./prog < ioccc.json > ioccc.html
|
||||
</code></pre>
|
||||
|
||||
<p>What’s not right with the output? How to fix it?</p>
|
||||
|
||||
<h3>Selected Judges Remarks:</h3>
|
||||
|
||||
<p>This entry exhibits a way of obfuscation we haven’t seen before, we think.
|
||||
The rulez of programming in an imperative language are violated, aren’t they?</p>
|
||||
|
||||
<p>Try figuring out how to increase the number of different colors, if you can.</p>
|
||||
|
||||
<h2>Author’s comments:</h2>
|
||||
|
||||
<p>Nowadays almost every programmer needs to do some Web chore. With all the open source stuff readily available, often we just need to call a bunch of libraries to generate an HTML page from a JSON feed.</p>
|
||||
|
||||
<p>This entry takes such decadence to an extreme. It just calls a bunch of libraries to generate an HTML page from a JSON feed, literally. There is no variable (function parameters included), no operator, no flow control statements except a few decorative returns. In compliance to production coding standards, the code is littered with fashionable jargon, doxygen comment, and license text.</p>
|
||||
|
||||
<p>As one would expect from such an approach, this program is much more resource intensive than it should be. And one needs a C99-compatible libc (with the common UNIX stuff) to build this and an HTML5-compatible browser to open the result. And it terminates with an assertion failure, but who cares if the web page is already generated?</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<TABLE><TR>
|
||||
<TD><a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/3.0/88x31.png" /></a></TD>
|
||||
<TD><P>© Copyright 1984-2018,
|
||||
<A HREF="/judges.html">Leo Broukhis, Simon Cooper, Landon Curt Noll</A>
|
||||
- All rights reserved<BR>
|
||||
This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
|
||||
<TD> <!--<a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
|
||||
</TR></TABLE>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,753 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="GENERATOR" content="mkd2html 2.1.5a DL=DISCOUNT">
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
|
||||
<link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="../hint.css">
|
||||
<title>Best of show</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Best of show</h1>
|
||||
|
||||
<p>Christopher Mills <a href="mailto:mrxo@sonic.net">mrxo@sonic.net</a><br>
|
||||
Twitter: @MisterXopher</p>
|
||||
|
||||
<h2>Judges' comments:</h2>
|
||||
|
||||
<h3>To use:</h3>
|
||||
|
||||
<pre><code>make
|
||||
./prog
|
||||
</code></pre>
|
||||
|
||||
<h3>Try:</h3>
|
||||
|
||||
<pre><code>make
|
||||
./prog
|
||||
(At the ">boot" prompt, type return)
|
||||
(At the ":" prompt, type "rk(0,0)rkunix")
|
||||
NOTE: To quit, press Control-E
|
||||
</code></pre>
|
||||
|
||||
<h3>Selected Judges Remarks:</h3>
|
||||
|
||||
<p>Do small machines only need small programs? This program weighs in at just
|
||||
3636 bytes, which is considerably lighter than the original machine it can replace.</p>
|
||||
|
||||
<p>This program can take you back to the start of everything, it is possible to
|
||||
run v0. Just type:</p>
|
||||
|
||||
<pre><code>make
|
||||
./v0
|
||||
|
||||
NOTE: To quit v0, press Control-E
|
||||
</code></pre>
|
||||
|
||||
<p>You will be greeted with a familiar prompt of “login”. The username and
|
||||
password are “dmr” and “dmr”. To make things more familiar you’ll need to
|
||||
create ‘.’ as it hasn’t been invented yet on this image!</p>
|
||||
|
||||
<pre><code>@ ln dd dmr .
|
||||
</code></pre>
|
||||
|
||||
<p>An “ls” will reveal that C hasn’t been invented yet! IOBCC anyone? The
|
||||
compiler is “bc”. It producess assembly, which will then need to be assembled
|
||||
together in this order “ops.s bl.s hello.s bi.s” to produce a.out!</p>
|
||||
|
||||
<p>But wait, we said this was the start of it all! This program can also run a
|
||||
program that replaces an even larger machine that can run BSD 2.9. To start this,</p>
|
||||
|
||||
<pre><code>make
|
||||
./prog
|
||||
|
||||
(At the ">boot" prompt, type return)
|
||||
(At the ":" prompt, type "rk(0,0)rkunix")
|
||||
NOTE: To quit prog, press Control-E
|
||||
</code></pre>
|
||||
|
||||
<p>This should now be very familiar and it is possible to compile and run one of
|
||||
the very first IOCCC entires “mullender.c”</p>
|
||||
|
||||
<p>But wait, there is even more! Try:</p>
|
||||
|
||||
<pre><code>make
|
||||
./v6
|
||||
|
||||
(At the "@" prompt, type "rkunix")
|
||||
NOTE: To quit v6, press Control-E
|
||||
</code></pre>
|
||||
|
||||
<h2>Author’s comments:</h2>
|
||||
|
||||
<blockquote><p> <em>This IOCCC entry is dedicated to the late Dennis M. Ritchie</em></p></blockquote>
|
||||
|
||||
<h1>The Program</h1>
|
||||
|
||||
<p>Since this is the 25th “annual” IOCCC, I thought I should mark the occasion
|
||||
with a look back to its earliest roots. At the same time the contest enters
|
||||
its 34th year of providing a safe forum for poor C code, the C language
|
||||
itself is fast approching its 50th anniversary, along with the UNIX operating
|
||||
system whose history is so entwined with.</p>
|
||||
|
||||
<p>The program delivered here is both a full machine emulation of the original
|
||||
PDP-7 that Ken Thompson used to write the first version of UNIX and a full
|
||||
machine emulation of the PDP-11/40 used by subsequent UNIXes. The <code>Makefile</code>
|
||||
can build versions that can run each of the following:</p>
|
||||
|
||||
<ol>
|
||||
<li> UNIX v0 for the PDP-7 (circa 1969)</li>
|
||||
<li> Research UNIX Version 6 (circa 1975)</li>
|
||||
<li> BSD 2.9 (circa 1983)</li>
|
||||
</ol>
|
||||
|
||||
|
||||
<p>For reasons to be described in a bit, the last (BSD 2.9) is the default.</p>
|
||||
|
||||
<h2>Building and Running BSD 2.9</h2>
|
||||
|
||||
<p>To run BSD 2.9, do <code>make</code> to build <code>prog</code> and then <code>./prog</code> to run it.</p>
|
||||
|
||||
<p>You should see a prompt from the first-stage bootloader that looks like</p>
|
||||
|
||||
<pre><code> >boot
|
||||
</code></pre>
|
||||
|
||||
<p>Type <code>RETURN</code> at this point and you will get to the second-stage boot loader
|
||||
that looks like</p>
|
||||
|
||||
<pre><code> 40Boot
|
||||
:
|
||||
</code></pre>
|
||||
|
||||
<p>The 40 in the prompt indicates that the bootloder has correctly determined
|
||||
that we are running on a PDP-11/40.</p>
|
||||
|
||||
<p>At this point, type the rather cryptic command <code>rk(0,0)rkunix</code> – this tells
|
||||
the system to look at the first partition on the first RK05 fixed disk, find
|
||||
the <code>rkunix</code> file and load it. You should eventually see the following:</p>
|
||||
|
||||
<pre><code> >boot
|
||||
|
||||
40Boot
|
||||
: rk(0,0)rkunix
|
||||
|
||||
Berkeley UNIX (Rev. 2.9.1) Sun Nov 20 14:55:50 PST 1983
|
||||
mem = 135872
|
||||
|
||||
CONFIGURE SYSTEM:
|
||||
xp ? csr 176700 vector 254 skipped: No CSR
|
||||
rk 0 csr 177400 vector 220 attached
|
||||
hk ? csr 177440 vector 210 skipped: No CSR
|
||||
rl ? csr 174400 vector 160 skipped: No CSR
|
||||
rp ? csr 176700 vector 254 skipped: No CSR
|
||||
ht 0 csr 172440 vector 224 skipped: No CSR
|
||||
tm 0 csr 172520 vector 224 skipped: No CSR
|
||||
ts 0 csr 172520 vector 224 skipped: No CSR
|
||||
dh ? csr 160020 vector 370 skipped: No CSR
|
||||
dm ? csr 170500 vector 360 skipped: No autoconfig routines
|
||||
dz ? csr 160110 vector 320 skipped: No CSR
|
||||
dz ? csr 160110 vector 320 skipped: No CSR
|
||||
dn 0 csr 175200 vector 300 skipped: No autoconfig routines
|
||||
vp ? csr 177500 vector 174 skipped: No autoconfig routines
|
||||
lp ? csr 177514 vector 200 skipped: No CSR
|
||||
Erase=^?, kill=^U, intr=^C
|
||||
#
|
||||
</code></pre>
|
||||
|
||||
<p>Congratulations, you are running BSD UNIX 2.9 in single-user mode as root.</p>
|
||||
|
||||
<p>On the other hand, if you did a typo somewhere, the boot loader has probably
|
||||
crashed and halted – if so, type Control-E to quit the simulation and try
|
||||
again. If you did really badly, you might have corrupted the virtual disk.
|
||||
If so, consider a <code>make clean</code> to start from scratch.</p>
|
||||
|
||||
<p>Assuming you managed to type 15 characters correctly, You should be at the
|
||||
root prompt. Most of the commands you are familiar with work here (this was
|
||||
only a quarter of a century ago – how much could things have changed?).
|
||||
Let’s try some:</p>
|
||||
|
||||
<pre><code> # ls
|
||||
.cshrc .profile boot hkunix mnt tmp
|
||||
.login 2.9stamp dev lib mullender.c unix
|
||||
.msgsrc bin etc lost+found rkunix usr
|
||||
# df
|
||||
Filesystem Mounted on kbytes used free % used
|
||||
/dev/rk0 / 1958 1688 270 86%
|
||||
# cc mullender.c
|
||||
# ./a.out
|
||||
</code></pre>
|
||||
|
||||
<p>The program you’ve just run was the <a href="http://ioccc.org/1984/mullender/mullender.c" title="mullender.c">winner of the first IOCCC contest from
|
||||
1984</a> (or was it 1894?), a personal favorite of mine. It is rather
|
||||
tightly bound to running on either a PDP-11 or a VAX. Now you have one.</p>
|
||||
|
||||
<p>Hitting Control-C will return you to the BSD UNIX prompt. Hitting Control-D
|
||||
will log you out of the single-user session and get you back to the <code>:login:</code>
|
||||
prompt. Here you can log in as <code>root</code> and get a full timesharing session.
|
||||
Feel free to try things like <code>vi</code>. I’ve taken the liberty of editing the
|
||||
<code>.login</code> and <code>.profile</code> files to set the console to a less traditional setup
|
||||
so that you don’t have to wait for the Model 33 KSR teletype to move its
|
||||
carriage. I’ve also predefined <code>TERM</code> to <code>vt100</code>, which will probably work
|
||||
well enough with whatever sort of ANSI terminal emulation you are using.</p>
|
||||
|
||||
<p>Note that I have not mounted the <code>/usr</code> disk here, so some commands from
|
||||
<code>/usr/bin</code> will be missing, along with all of the <code>man</code> pages. They are
|
||||
<a href="http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.9BSD" title="2.9 BSD">available online</a> if you need them. Adding a second RK05 disk was
|
||||
possible, but I didn’t get around to it… As the Judges can no doubt attest,
|
||||
“Mid 2017” creeps up on you quicker than you expect. :)</p>
|
||||
|
||||
<p>Once you’ve had enough fun in BSD 2.9, type Control-E to exit the emulation.</p>
|
||||
|
||||
<h2>Building and Running Research UNIX v6</h2>
|
||||
|
||||
<p>Research UNIX v6 and BSD 2.9 use the same executable, but require a different
|
||||
disk image. Type <code>make v6</code> to build it, then type <code>./prog</code> to run it.</p>
|
||||
|
||||
<p>You should see the boot loader prompt which is a single <code>@</code>:</p>
|
||||
|
||||
<pre><code> @
|
||||
</code></pre>
|
||||
|
||||
<p>At this point, you again must type a special incantation: <code>rkunix</code>. After that
|
||||
you should see:</p>
|
||||
|
||||
<pre><code> @rkunix
|
||||
mem = 1035
|
||||
RESTRICTED RIGHTS
|
||||
|
||||
Use, duplication or disclosure is subject to
|
||||
restrictions stated in Contract with Western
|
||||
Electric Company, Inc.
|
||||
#
|
||||
</code></pre>
|
||||
|
||||
<p>You are now running a single-user session of v6 UNIX. You might want to start
|
||||
with <code>stty -lcase</code> because otherwise everything will be IN ALL CAPS.</p>
|
||||
|
||||
<p>Again, if you failed typing seven characters without making a mistake, you
|
||||
may need to use Control-E to quit the simulation.</p>
|
||||
|
||||
<p>Assuming you’re more careful than that, we can try a few commands:</p>
|
||||
|
||||
<pre><code> @rkunix
|
||||
mem = 1035
|
||||
RESTRICTED RIGHTS
|
||||
|
||||
Use, duplication or disclosure is subject to
|
||||
restrictions stated in Contract with Western
|
||||
Electric Company, Inc.
|
||||
# STTY -LCASE
|
||||
# ls
|
||||
bin
|
||||
dev
|
||||
etc
|
||||
hpunix
|
||||
lib
|
||||
mnt
|
||||
rkunix
|
||||
rpunix
|
||||
tmp
|
||||
unix
|
||||
usr
|
||||
# cat > foo.c
|
||||
main()
|
||||
{
|
||||
printf("Hello, World!\n");
|
||||
}
|
||||
# cc foo.c
|
||||
# ./a.out
|
||||
Hello, World!
|
||||
</code></pre>
|
||||
|
||||
<p>Why is Version 6 interesting? Well, it was the oldest version that I could
|
||||
find a boot image of that had a C compiler… This C compiler is recognizably
|
||||
C, but not quite the same syntax as we have today. It’s much closer to the
|
||||
<a href="https://www.bell-labs.com/usr/dmr/www/kbman.html" title="B Language">B language</a> from which it is derrived. In particular, this C compiler
|
||||
would not be able to compile <code>mullender.c</code> (as simple as it is), because the
|
||||
following syntax features don’t exist yet:</p>
|
||||
|
||||
<ul>
|
||||
<li>The <code>short</code> data type doesn’t exist yet. Only <code>int</code> (<code>short</code> will show
|
||||
up when <code>long</code> comes, and the port to the Interdata 7/32 starts to make
|
||||
the idea of portability become important).</li>
|
||||
<li>Hexidecimal constants don’t exist yet. Digital’s computers all used
|
||||
octal.</li>
|
||||
<li>The array initializer syntax hasn’t yet moved to using <code>=</code>. It still uses
|
||||
the older form taken from B, which looks like <code>array[] { 1, 2, 3 };</code></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>It can still compile “Hello World!” (note that you must type a Control-D after
|
||||
you finish entering the code, to let <code>cat</code> see an end-of-file).</p>
|
||||
|
||||
<p>This version of UNIX doesn’t go into multi-user mode if you do a Control-D.
|
||||
Single-user mode was entered because the front-panel console switches were
|
||||
set to the magic number 0173030 (this can be changed with a re-compile).</p>
|
||||
|
||||
<p>Once you are done with Version 6, Type Control-E to exit the simulation.</p>
|
||||
|
||||
<p>Note that since both BSD 2.9 and UNIX v6 use the same PDP-11/40 emulation
|
||||
code, and they use the same name for the disk (<code>rk05.fs</code>), if you want to go
|
||||
back to the BSD simulation, you should either delete <code>rk05.fs</code> or do a
|
||||
<code>make clean</code> before you do a <code>make</code>.</p>
|
||||
|
||||
<h2>Building and Running UNIX v0</h2>
|
||||
|
||||
<p>We now set the Wayback Machine to the very start of it all, 1969.</p>
|
||||
|
||||
<p><a href="https://www.bell-labs.com/usr/dmr/www/hist.html" title="UNIX history">The story</a> here is interesting and well worth a read. Bell Labs was
|
||||
pulling out of the Multics project and Ken Thompson and his collegues had
|
||||
become accustomed to the relatively nice programming environment. They also
|
||||
enjoyed the early computer game <a href="https://www.bell-labs.com/usr/dmr/www/spacetravel.html" title="Space Travel"><em>Space Travel</em></a> and wanted another system
|
||||
to run it on. They found a PDP-7 which was already obsolete at the time to
|
||||
port <em>Space Travel</em> to. The primitive programming environment influenced
|
||||
Thompson to recreate parts of the Multics experience in the much more
|
||||
hardware-constrained PDP-7 environemnt. In the summer of 1969, with his wife
|
||||
out on a month-long vacation, Thompson re-wrote a filesystem emulation he had
|
||||
been experementing with to include an assembler, a shell, an editor and an
|
||||
operating system kernel and hence created the first version of UNIX (although
|
||||
it hadn’t been named that yet).</p>
|
||||
|
||||
<p>You can try out this version by typing <code>make v0</code>. Since this version is a
|
||||
native PDP-7 emulation, it gets its own binary. Type <code>./v0</code> to run it. You
|
||||
should see the login prompt.</p>
|
||||
|
||||
<pre><code> login:
|
||||
</code></pre>
|
||||
|
||||
<p>There are two user accounts <code>ken</code> and <code>dmr</code>, with the passwords <code>ken</code> and <code>dmr</code>
|
||||
respectively. Let’s try the Dennis Richie’s <code>dmr</code> account:</p>
|
||||
|
||||
<pre><code> login: dmr
|
||||
password: dmr
|
||||
@ ls
|
||||
. ?
|
||||
</code></pre>
|
||||
|
||||
<p>Even though this is not Ken’s doing, I feel this gives me licence to
|
||||
include this quote from the BSD <code>fortune</code> program:</p>
|
||||
|
||||
<blockquote><p>Ken Thompson has an automobile which he helped design. Unlike
|
||||
most automobiles, it has neither speedometer, nor gas gauge,
|
||||
nor any of the numerous idiot lights which plague the modern
|
||||
driver. Rather, if the driver makes any mistake, a giant “?”
|
||||
lights up in the center of the dashboard. “The experienced
|
||||
driver”, he says, “will usually know what’s wrong.”</p></blockquote>
|
||||
|
||||
<p>What’s the deal here? Well, that’s a slightly long story. The short version
|
||||
is we have gone so far back in the history of UNIX that <em>we don’t have
|
||||
filesystem paths yet</em>. In other words, we can’t say something like
|
||||
<code>/bin/ls</code> yet, and the shell can’t store that path in <code>$PATH</code> to search for it.
|
||||
We also haven’t invented <code>.</code> or <code>..</code> yet. In fact, the filesystem isn’t even
|
||||
the traditional UNIX tree structure, it’s a directed graph of hard links…</p>
|
||||
|
||||
<p><code>ls</code> needs to be able to read ‘<code>.</code>’, the current directory. <code>dmr</code>’s home
|
||||
directory doesn’t have that yet, but we can make it, because the home
|
||||
directory has a hard link to <code>dd</code>, which is the directory that holds all
|
||||
of the user home directories (this will eventually become <code>/</code>, the root
|
||||
path). We can do</p>
|
||||
|
||||
<pre><code> @ ln dd dmr .
|
||||
</code></pre>
|
||||
|
||||
<p>To make the new link (note that <code>ln</code> doesn’t support paths either, so you have
|
||||
to give it three arguments – a directory in the current dir, a file in that
|
||||
directory, and the new name).</p>
|
||||
|
||||
<p>Now <code>ls</code> will work, and we can try some other things while we are here:</p>
|
||||
|
||||
<pre><code> login: dmr
|
||||
password: dmr
|
||||
@ ln dd dmr .
|
||||
@ ls
|
||||
dd
|
||||
system
|
||||
as.s
|
||||
b_readme
|
||||
bi.s
|
||||
bl.s
|
||||
db.s
|
||||
hello.b
|
||||
ops.s
|
||||
.
|
||||
@ cat b_readme
|
||||
Here is how to compile and run hello.b:
|
||||
|
||||
@ bc hello.b hello.s
|
||||
@ as ops.s bl.s hello.s bi.s
|
||||
I
|
||||
II
|
||||
ops.s
|
||||
bl.s
|
||||
hello.s
|
||||
bi.s
|
||||
@ a.out
|
||||
Hello, World!
|
||||
|
||||
|
||||
@ bc hello.b hello.s
|
||||
@ as ops.s bl.s hello.s bi.s
|
||||
I
|
||||
II
|
||||
ops.s
|
||||
bl.s
|
||||
hello.s
|
||||
bi.s
|
||||
@ a.out
|
||||
Hello, World!
|
||||
@
|
||||
</code></pre>
|
||||
|
||||
<p>The last command is invoking the compiler for an exteremely early version of
|
||||
the <a href="https://www.bell-labs.com/usr/dmr/www/kbman.html" title="B Language">B programming language</a>, the predecessor to C. Thompson missed the
|
||||
convinience of writing code in a high-level language – Multics was written
|
||||
a version of PL/1 – and wanted the same convinience on UNIX. He preferred
|
||||
BCPL (a typeless language) to PL/1. As Dennis Ritchie <a href="https://www.bell-labs.com/usr/dmr/www/chist.html" title="C History">wrote</a>:</p>
|
||||
|
||||
<blockquote><p>B can be thought of as C without types; more accurately,
|
||||
it is BCPL squeezed into 8K bytes of memory and filtered
|
||||
through Thompson’s brain.</p></blockquote>
|
||||
|
||||
<p>A look at the B reference manual will show the strong correlation with C, and
|
||||
shows the source of a lot of C’s mysteriousness – some of which is preserved
|
||||
simply so that C could compile the <em>dozens</em> of lines of existing B code…</p>
|
||||
|
||||
<p>Thompson’s assembler was also extremely simple. It didn’t even know about
|
||||
opcodes – these need to be defined in the first assembly file, with the
|
||||
assembler OR-ing the opcode fields together (space was the “operator” for
|
||||
logical OR). There is no link step – all files are provided to the assembler
|
||||
on the command line, concatenated together and assembled, producing a single
|
||||
<code>a.out</code> (assembler output) file. Even after UNIX got a linker, <code>a.out</code>
|
||||
remained the default name of the binary generated by the linker (and hence
|
||||
also by <code>cc</code>).</p>
|
||||
|
||||
<p>This system is still has the familiarity of UNIX, with all the two- and
|
||||
three-letter commands, device files, shell redirection, the same core system
|
||||
calls (<code>read</code>, <code>write</code>, <code>open</code>, <code>close</code>, <code>creat</code>, <code>fork</code>, etc.). There are a
|
||||
number of differences still:</p>
|
||||
|
||||
<ul>
|
||||
<li>As noted, there are no file paths</li>
|
||||
<li><code>read</code> and <code>write</code> do I/O on (18-bit) words. Character I/O to files needs
|
||||
to unpack those to bytes, and of course deal with <code>NUL</code> characters.</li>
|
||||
<li><code>exec</code> was performed by the shell directly. Arguments are passed as
|
||||
four words (eight bytes), and space padded. This matches the format for
|
||||
file names for <code>open</code> and <code>creat</code>.</li>
|
||||
<li><code>wait</code> does not yet exist. A more complicated mechanism for sending and
|
||||
recieving messages (<code>smes</code> and <code>rmes</code>) are used instead.</li>
|
||||
<li>File permission bits are all different, since groups don’t exist yet.</li>
|
||||
<li>User programs are not allowed to run during disk I/O. This is because the
|
||||
disk controller’s “data break” (DMA) accesses were so fast relative to the
|
||||
CPU that transfers would be dropped if an instruction that used
|
||||
“deferred” mode (indirection) was executed. This also meant that the
|
||||
“program break” (interrupt) routine in the kernel had to specifically
|
||||
avoid deferred accesses by using self-modifying code to do indirection
|
||||
through pointers.</li>
|
||||
<li>Although the PDP-7 suppoted a “trap mode” (a primitive supervisor mode),
|
||||
the UNIX kernel doesn’t use it. This means that user programs could alter
|
||||
or crash the kernel at will (in fact, there is a system call that returns
|
||||
addresses of useful kernel routines so that user code can call them
|
||||
directly).</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>As usual, when you are done exploring UNIX v0, type Control-E to exit the
|
||||
simulator.</p>
|
||||
|
||||
<h1>About the Program</h1>
|
||||
|
||||
<p>The program came about when I was looking for something to honor the pending
|
||||
50th anniversary of the C language (because of the mercurial nature of IOCCC
|
||||
contest scheduling, I chose not to wait for the actual 50th anniversary).
|
||||
I had though of writing self-hosting compilers for a stripped-down version of
|
||||
C, or maybe even a version of the B language… At the same time, I was
|
||||
obsessed with the idea of allowing <code>mullender.c</code> from 1984 to run. Although
|
||||
that was still a possibility on an interpreted version of B or a stripped-down
|
||||
version of C, it felt cheap, as it would be <code>mullender.c</code> only in spirit.</p>
|
||||
|
||||
<p>It was during this time that I discovered that in 2016, members of the Unix
|
||||
Heritage Society got access to <a href="http://www.tuhs.org/Archive/Distributions/Research/McIlroy_v0/" title="V0 Scans">printouts of assembly-language source for the
|
||||
original version of UNIX</a>. With what was a <a href="http://minnie.tuhs.org/Y5/wkt_hapop_paper.pdf" title="UNIX v0">huge amount of work</a>,
|
||||
they scanned in the printouts, fixed up the OCR translations, built assembler
|
||||
and file system tools from scratch and made an accurate simulation of
|
||||
Thompson’s PDP-7 that allowed them to get the system up and running. Although
|
||||
source for the entire kernel and about half of the user-space commands were
|
||||
present (including the runtime and libraries for the B compiler), the
|
||||
remainder needed to be written from scratch, including the shell. The final
|
||||
results of the project are <a href="https://github.com/DoctorWkt/pdp7-unix" title="PDP-7 UNIX">available on github</a>.</p>
|
||||
|
||||
<p>None of this was remotely easy (as I was to discover myself). The PDP-7 is
|
||||
long gone, and the documentation for it is less complete than one would like.
|
||||
In addition, the devices attached for it were a bit of a mystery. The disk
|
||||
system is referenced only in an old price list. It was a RB09 fixed disk,
|
||||
probably made by Burroughs. It is close to what was called the RC10 for the
|
||||
PDP-10, but with a different interface. And the system also included a custom
|
||||
display device called Graphics-2, which had been built in-house by AT&T.
|
||||
It can’t be completely ignored, because the kernel itself pokes at it (the
|
||||
UNIX crew used it as a second terminal – a “glass TTY”).</p>
|
||||
|
||||
<p>I decided that implementing this PDP-7 would be possible as an IOCCC entry.</p>
|
||||
|
||||
<p>The emulator emulates the full machine:</p>
|
||||
|
||||
<ul>
|
||||
<li>PDP-7 Central Processor</li>
|
||||
<li>Core Memeory Module Type 147 – extends the core to 8,192 18-bit words</li>
|
||||
<li>Extended Arithmetic Element Type 177 – adds one’s-complement
|
||||
multiplication, division and shifting</li>
|
||||
<li>Real Time Clock</li>
|
||||
<li>Teletype Model 33 KSR</li>
|
||||
<li>Perforated Tape Reader Type 444</li>
|
||||
<li>RB09 Fixed Disk Controller</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>The <a href="http://bitsavers.trailing-edge.com/pdf/dec/pdp7/F-75P_PDP7prelimUM_Dec64.pdf" title="PDP-7 Manual">PDP-7</a> is an odd duck by modern computer standards:</p>
|
||||
|
||||
<ul>
|
||||
<li>18 bit words, with no byte addressing.</li>
|
||||
<li>Both one’s and two’s complement math (there is <code>ADD</code> for one’s complement
|
||||
and <code>TAD</code> for two’s complement). The EAE is entirely one’s-complement.</li>
|
||||
<li>“Microcoded” instructions.</li>
|
||||
<li>Auto-increment memory locations.</li>
|
||||
<li>Non-reentrant function calls (the return address is stored at the indicated
|
||||
address and the PC jumps to the location after it).</li>
|
||||
<li>The <code>XCT</code> instruction, that executes the word loaded from memory as an
|
||||
instruction.</li>
|
||||
<li>An instruction <code>LAW</code> that loads the instruction opcode into the
|
||||
accumulator.</li>
|
||||
<li>Heavy use of “inline” operands. For instance the <code>MUL</code> instruction expects
|
||||
the second operand to be stored in memory after the instruction. This
|
||||
pretty much requires the use of self-modifying code.</li>
|
||||
<li>No immediates. Almost all constants have to live in memory locations and
|
||||
be referenced by address.</li>
|
||||
<li>Common operations, like “subtract” and “inclusive OR” are not directly
|
||||
supported on the machine and require multiple instructions and some spare
|
||||
memory locations to support. Being clever also helps.</li>
|
||||
<li>Single accumulator architecture. No direct support for things like stacks.</li>
|
||||
<li>I/O is done with dedicated I/O instructions (which are also microcoded).</li>
|
||||
<li>The RB09 disk controller gets a special mention here because of its
|
||||
particularly annoying encoding of track and sector offsets in
|
||||
<a href="https://en.wikipedia.org/wiki/Binary-coded_decimal" title="BCD">packed BCD</a>. A non-trivial amount of code space in the simulator
|
||||
is needed to convert into and out of BCD, along with an equivalent amount
|
||||
of code in the UNIX kernel itself.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>The simulation handles everything I was able to discover about the PDP-7, even
|
||||
things that the UNIX code itself doesn’t use. For instance, it correctly
|
||||
implements the “trap mode” feature (a primitive form of supervisor mode) even
|
||||
though the kernel does not enable it. It also implements the microcoding of
|
||||
the EAE instructions even though the UNIX environment uses only the standard
|
||||
encodings. If you wanted to do a 11-bit multiply instead of an 18-bit one,
|
||||
it will probably work.</p>
|
||||
|
||||
<p>The simulation starts by loading a boot program off of the virtualized paper
|
||||
tape, which is in a modified version of the RIM boot loader format. The
|
||||
RIM format encodes each 18-bit word as three six-bit characters, using one bit
|
||||
to denote the final word (which is executed directly and is usually a <code>JMP</code> or
|
||||
<code>HLT</code> instruction). The load address comes from the console address switches.
|
||||
Both of these are controlled by compile-time flags.</p>
|
||||
|
||||
<p>The emulator continues emulating instructions until it sees a <code>HLT</code> instruction
|
||||
which will cause it to exit. Console I/O is emulated by setting the terminal
|
||||
into raw mode and polling via <code>read</code>. Line-clock ticks (at 60 Hz) are done
|
||||
by polling <code>gettimeofday</code>. Dynamic frequency code arranges to reduce the
|
||||
polling interval to a few polls per tick, so that simulation remains
|
||||
responsive. Since we use the real wall-clock time, this means that the
|
||||
emulated system will see time advance at the correct rate.</p>
|
||||
|
||||
<h2>Licencing Fun</h2>
|
||||
|
||||
<p>So now I have a system that can run UNIX v0. One problem remains… I don’t
|
||||
have permission to submit UNIX v0 to the IOCCC. It is not my code and the
|
||||
copyright for it remains the property of whoever owns that part of what was
|
||||
once Bell Labs – I believe it is Nokia at this point. I have worked around
|
||||
this problem in two ways:</p>
|
||||
|
||||
<p>First, I didn’t submit the source code or binary image for v0 UNIX as part of
|
||||
my IOCCC entry. I merely submitted a <code>Makefile</code> that can issue a <code>curl</code>
|
||||
command to fetch a prebuilt v0 disk image from the github repository. I am
|
||||
hoping this is considered part of “Legal abose of the rules” which is supposed
|
||||
to be “somewhat encouraged”. As per RULE 12, I am justifying said abuse here,
|
||||
in the remarks file.</p>
|
||||
|
||||
<p>Secondly, the choice to run the UNIX v0 code is optional. If you are worried
|
||||
about Nokia’s lawyers running you to ground for running a 50-year old copy
|
||||
of a binary image for a machine that is almost completely nonexistant, you
|
||||
can just not do so. Delete the lines from the <code>Makefile</code> and sleep well.
|
||||
You still have two other UNIXes to play with.</p>
|
||||
|
||||
<p>What about the other two UNIX variants? These are both covered by licences
|
||||
that allow me to use them. Back in 2002, Caldera International released
|
||||
Research Unix versions 1-7 and 32V under a <a href="http://www.tuhs.org/Archive/Caldera-license.pdf" title="Caldera Licence">permissive BSD-like license</a>.
|
||||
BSD UNIX is based off of v7 UNIX, and of course has its own permissive
|
||||
BSD licence. And in 2017, Nokia also released versions 8-10 under the
|
||||
condition that it will not assert copyright rights for non-commercial use.</p>
|
||||
|
||||
<p>So the newer UNIXes are in the clear. I doubt anyone actually cares about
|
||||
version 0 either, but technically it’s still under copyright.</p>
|
||||
|
||||
<h2>PDP-11/40</h2>
|
||||
|
||||
<p>So if I have a PDP-7 emulator, how do I run operating systems that expect a
|
||||
PDP-11? Simple… <em>I emulate a PDP-11/40 on the PDP-7</em>. I have written
|
||||
PDP-7 assembler code to emulate a PDP-11/40 with the following equipment:</p>
|
||||
|
||||
<ul>
|
||||
<li>PDP-11/40 (KD11-A)</li>
|
||||
<li>EIS instruction set (KE11-E)</li>
|
||||
<li>Memory management unit (KJ11-A)</li>
|
||||
<li>Line time clock (KT11-D)</li>
|
||||
<li>124 Kwords of memory (244 Kbytes)</li>
|
||||
<li>RK05 fixed disk drive (RK11)</li>
|
||||
<li>Console TTY (DL11)</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>This required a few tweaks to the emulator. The first problem is that the
|
||||
RK05 disk is about 2.5 MB, but the RB09 is only about 2 MB. That’s easily
|
||||
solveable – just add more tracks to the RB09. UNIX v0 is unlikely to notice
|
||||
(although the number of tracks is a compile time parameter, and the <code>v0</code>
|
||||
build commands set it to the correct value).</p>
|
||||
|
||||
<p>The second problem is that we are simulating a system that can have up to
|
||||
124 Kwords of memory on a system with only 8 Kwords total. That meant I needed
|
||||
to virtualize the PDP-11/40’s physical memory (and add a few more tracks to
|
||||
the disk to hold the virtualization).</p>
|
||||
|
||||
<p>A large amount of time was spent tuning this code to be efficient. The
|
||||
memory virtualization uses part of the 8 Kword memory as an LRU cache, and
|
||||
uses a number of first-level microcaches to avoid having to do the LRU updates.
|
||||
This also serves to offload the complexity of the PDP-11’s segmentation logic
|
||||
from a large number of memory accesses (the PDP-11 does as many as eight
|
||||
accesses per instruction). Despite the super fast emulated disk, the PDP-7
|
||||
code in the emulator is slow, mostly because it has to do a bunch of divides
|
||||
to convert the linear disk offset into a BCD-coded track and sector for the
|
||||
emulated RB09. I/O polling is again used, except this time it uses the
|
||||
PDP-7’s “skip on flag set” I/O instructions. As with the PDP-7 emulator
|
||||
itself, the PDP-11 emulator dynamically measures the instruction throughput
|
||||
relative to the line-clock tick, so that it only polls for I/O a few times
|
||||
per tick.</p>
|
||||
|
||||
<p>The one remaining problem is building the disk images themselves. Since the
|
||||
PDP-11’s disk is 16-bit, but the PDP-7’s is 18-bit (which the emulator stores
|
||||
in 32-bit <code>int</code>s), a conversion program is needed to unpack the binary disk
|
||||
images from 16 bits per word to 32. This in turn needs to be done in the
|
||||
<code>Makefile</code> using standard POSIX tools, which aren’t exactly good with binary.
|
||||
I had a wierdly clever way to do this with <code>od</code>, <code>awk</code> and <code>uudecode</code> that
|
||||
I will leave as an exercise for the curious, but I decided it would be easier
|
||||
to do it with the PDP-7 emulator itself, feeding a simple program in on its
|
||||
boot tape. This required an additional tweak to the emulator, since by default
|
||||
its console TTY is not eight-bit clean (in fact, UNIX v0 expects to see the
|
||||
MSB set on the terminal reads, and sets it on writes, what is called “mark”
|
||||
parity). This is also enabled by a compile-time setting (used only for the
|
||||
<code>builddisk</code> program).</p>
|
||||
|
||||
<p>Despite the complexity of the PDP-11 instruction set and its emulated I/O
|
||||
devices and the corresponding primitiveness of the PDP-7’s instruction set,
|
||||
the emulation itself is a suprisingly small amount of code, not really taxing
|
||||
the 8 Kword memory, with about 2.25 Kwords of actual code and a similar
|
||||
amount of space for the memory virtualization cache and disk block buffer,
|
||||
leaving nearly half (3.5 Kwords) of the memory unused. The simulator executes
|
||||
somewhere around 250 PDP-7 instructions per PDP-11 instruction. On my laptop,
|
||||
the PDP-7 is running somewhere in the neighborhood of 70 MIPS, which means the
|
||||
PDP-11 is running at about 0.3 MIPS, which is probably not too far off of its
|
||||
actual speed (the cycle time of an 11/40 was around a microsecond for simple
|
||||
instructions, but could be proportionally larger for instructions that did
|
||||
multiple memory accesses, which many did).</p>
|
||||
|
||||
<p>As an aside, although the idea of emulating the PDP-11 on an emulated PDP-7
|
||||
came about from the realization that I needed a response to the late-discovered
|
||||
licence issue, I’m quite pleased with the result – it enables an interesting
|
||||
window on the dawn of the UNIX era. I feel that someone should complete the
|
||||
circle here by emulating a VAX 780 on the PDP-11 and run 4.2BSD on it, so that
|
||||
we can get the <a href="https://groups.google.com/forum/?hl=en#!msg/net.lang.c/lx-TAuEyeRI/HdOOnNx6LC0J" title="First annual IOCCC announcement">original runtime environment used for the first IOCCC</a>.</p>
|
||||
|
||||
<h2>Compile-time Options</h2>
|
||||
|
||||
<p>The following command flags control the compilation:</p>
|
||||
|
||||
<ul>
|
||||
<li><code>-DI="image.fs"</code>: Name of the disk image file. This must be created
|
||||
offline, and be of the correct size to avoid segmentation violations.</li>
|
||||
<li><code>-DA=4096</code>: Setting of the console address switches. This tells the RIM
|
||||
bootloader where to load the boot image.</li>
|
||||
<li><code>-DS=0</code>: Setting of the console data switches. The PDP-7 emulation can
|
||||
read these with the microcoded <code>OAS</code> (OR switches into AC) instruction.
|
||||
By proxy, the PDP-11 emulation can read them via the <code>CSW</code> device.</li>
|
||||
<li><code>-DW=MAP_PRIVATE</code>: This sets the memory mapping for <code>mmap</code>. Setting to
|
||||
<code>MAP_PRIVATE</code> makes the disk image be copy-on-write. Setting it to
|
||||
<code>MAP_SHARED</code> makes the disk image be sharable. Do the latter if you want
|
||||
to preserve the disk contents between sessions.</li>
|
||||
<li><code>-DT=</code>: List of initializers for the <code>termios</code> structure. The v0 UNIX
|
||||
expects the terminal to be in half-duplex mode, echoing its input, with
|
||||
swapped CR and NL. The PDP-11 UNIXes don’t.</li>
|
||||
<li><code>-DX=5</code>: The ASCII code of the control character that causes the simulation
|
||||
to abort. If set to 0, there is no abort code.</li>
|
||||
<li><code>-DY=128</code>: Controls console I/O parity. If set to zero, the console is
|
||||
eight-bit clean. If set to 128, the high bit is set on keyboard reads and
|
||||
masked off on printer output (“mark” parity). UNIX v0 expects the latter.</li>
|
||||
<li><code>-DV=270</code>: The size of the disk, in tracks. The UNIX v0 disk has 200
|
||||
tracks (each has 80 sectors of 64 18-bit words). The PDP-11 UNIXes
|
||||
increase this to 270, to allow for the larger RK05 disk emulation
|
||||
(406 tracks of twelve 256-word sectors), plus the space for the 124 Kwords
|
||||
of virtualized memory and the 8 Kwords of emulator code.</li>
|
||||
<li><code>-DP="xxx"</code>: RIM bootstrap program paper tape image. Be careful with the
|
||||
quoting here – there is at least three levels going on. In particular,
|
||||
you will need to escape <code>$</code> as <code>$$</code> to protect it from <code>make</code>.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>What is the ASCII art supposed to be?</h2>
|
||||
|
||||
<p>The ASCII art represents a torn piece of <a href="https://en.wikipedia.org/wiki/Punched_tape" title="Paper Tape">paper tape</a>.</p>
|
||||
|
||||
<h2>Acknowledgements</h2>
|
||||
|
||||
<p>None of this could have been possible without the hard work of</p>
|
||||
|
||||
<ul>
|
||||
<li>Warren Toomey and the other members of the
|
||||
<a href="http://www.tuhs.org" title="The Unix Heritage Society">The Unix Heratage Society</a></li>
|
||||
<li>Robert M. Supnik and the other contributors to <a href="http://simh.trailing-edge.com" title="SimH">SimH</a>, the simulator
|
||||
for historic computer architectures. The number of times I needed to
|
||||
“Use the Source, Luke” on SimH to unravel some dark corner of these
|
||||
machines was uncountable.</li>
|
||||
<li><a href="http://bitsavers.trailing-edge.com" title="Bitsavers.org">Bitsavers</a>, which acquired, scanned and preserved all the manuals
|
||||
I spent many hours squinting at.</li>
|
||||
<li>Ken Thompson, Dennis Ritchie, Brian Kernigan, M. D. McIlroy, J. F.
|
||||
Osssanna, Rudd Canaday and the other members of the Bell Labs
|
||||
Computing Science Research Center who were responsible for the invention
|
||||
of UNIX, the C programming language, and the innumerable other innovations
|
||||
that we now take for granted as part of the modern software landscape.
|
||||
In particular, the <a href="https://www.bell-labs.com/usr/dmr/www/" title="DMR Homepage">home page of the late Dennis Ritchie</a> contained
|
||||
a trove of useful information on the evolution of UNIX and C and is
|
||||
recommended for perusal by others who share my peculiar retrocomputing
|
||||
affectations.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>Finally, thanks to my spouse for putting up with the many hours I spent on this
|
||||
nonsense, and treating “I’m working on my IOCCC entry” as an acceptable answer
|
||||
to queries about how I was spending my free time. Similarly, I apologise to
|
||||
those friends and coworkers who had to listen to me complain about obscure
|
||||
corner-case bugs in my code. The obsession is over, at least until next
|
||||
time…</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<hr />
|
||||
|
||||
<TABLE><TR>
|
||||
<TD><a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/3.0/88x31.png" /></a></TD>
|
||||
<TD><P>© Copyright 1984-2018,
|
||||
<A HREF="/judges.html">Leo Broukhis, Simon Cooper, Landon Curt Noll</A>
|
||||
- All rights reserved<BR>
|
||||
This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
|
||||
<TD> <!--<a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
|
||||
</TR></TABLE>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,157 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="GENERATOR" content="mkd2html 2.1.5a DL=DISCOUNT">
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
|
||||
<link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="../hint.css">
|
||||
<title>Most stellar</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Most stellar</h1>
|
||||
|
||||
<p>Timo Poikola <a href="mailto:ioccc2018@ig.fi">ioccc2018@ig.fi</a><br>
|
||||
<a href="https://ig.fi/">https://ig.fi/</a></p>
|
||||
|
||||
<h2>Judges' comments:</h2>
|
||||
|
||||
<h3>To use:</h3>
|
||||
|
||||
<pre><code>make
|
||||
|
||||
./prog
|
||||
</code></pre>
|
||||
|
||||
<h3>Try:</h3>
|
||||
|
||||
<p>On terminal supports 24 bit color, has black background, and size at least 125x38, try:</p>
|
||||
|
||||
<pre><code>./prog
|
||||
</code></pre>
|
||||
|
||||
<h3>Selected Judges Remarks:</h3>
|
||||
|
||||
<p>It is said by some students of Astronomy:</p>
|
||||
|
||||
<pre><code>Oh, Be A Fine Gal, Kiss Me!
|
||||
Oh, Be A Fine Gentleman, Kiss Me!
|
||||
</code></pre>
|
||||
|
||||
<p>Many <a href="http://www.star.ucl.ac.uk/%7Epac/obafgkmrns.html">Mnemonic variations</a> exist.
|
||||
You might wish, on a star, to better understand the colors being displayed.
|
||||
And those in the deep south might wish to go north for a better view.</p>
|
||||
|
||||
<h2>Author’s comments:</h2>
|
||||
|
||||
<h3>How to build</h3>
|
||||
|
||||
<pre><code>gcc -o prog -std=gnu11 -O3 prog.c
|
||||
</code></pre>
|
||||
|
||||
<p>or</p>
|
||||
|
||||
<pre><code>make
|
||||
</code></pre>
|
||||
|
||||
<h3>Poster</h3>
|
||||
|
||||
<p>You can generate an A3 sized poster by <em>make docs</em>. This command creates a pdf file <em>poikola.pdf</em>.</p>
|
||||
|
||||
<h3>What this entry does</h3>
|
||||
|
||||
<h4>Introduction</h4>
|
||||
|
||||
<p>It was a starry night when my wife pointed her finger up and asked: “What is this star and may I have some Easter eggs?”</p>
|
||||
|
||||
<p>So I had to sit down and solve those tricky questions with Nano and a C compiler.</p>
|
||||
|
||||
<h4>Little spoilers</h4>
|
||||
|
||||
<p>Basically, the program draws animated ASCII art of the Big Dipper using Annie Jump Cannon’s spectral classification system of stars and I think the
|
||||
colors of the output are as accurate as possible.</p>
|
||||
|
||||
<p>This program also tells once in a year if it is correct time to find and eat some Easter eggs.</p>
|
||||
|
||||
<p>The program has also at least three other functions, obvious and not so obvious.</p>
|
||||
|
||||
<h4>Technical jargon</h4>
|
||||
|
||||
<p>This program has been tested on xterm and Konsole and also Linux virtual terminal. Color support in the terminal is not necessary, but the effect is better with it.
|
||||
This entry has partial support for terminals with a white background but the best viewing experience is achieved when the terminal in use supports 24-bit colors,
|
||||
has a black background and the size is at least 125x38.</p>
|
||||
|
||||
<p>Special note for Mac users: <strong>Terminal</strong> does not work as expected you might need xterm from XQuartz or some other
|
||||
working terminal. Thanks to Dave Burton for spotting this problem.</p>
|
||||
|
||||
<p>The main reason for the header <code>unistd.h</code> is <code>getdelim()</code> but once I included it I also abused other functions and defines. This header is mutually exclusive with <em>-std=c11</em>.</p>
|
||||
|
||||
<p>The program was developed with little-endian machines; I tried to support big-endian too, but this support is somewhat limited.</p>
|
||||
|
||||
<p>This program has been compiled in</p>
|
||||
|
||||
<ol>
|
||||
<li>i386 (Debian Stretch) with gcc and clang</li>
|
||||
<li>amd64 (Debian Buster) with gcc and clang</li>
|
||||
<li>Raspberry Pi 3 (Debian stretch) with gcc and clang</li>
|
||||
<li>Lego Mindstorms EV3 Intelligent Brick (Debian Jessie) with gcc and clang (in this case, compiling time with clang-3.5 12 seconds and with gcc 27 seconds)</li>
|
||||
</ol>
|
||||
|
||||
|
||||
<h3>Warnings and restrictions required by law</h3>
|
||||
|
||||
<p>Please do not feed little babies chocolate.</p>
|
||||
|
||||
<h3>Major spoilers</h3>
|
||||
|
||||
<div style="margin-bottom:61em;"> </div>
|
||||
|
||||
|
||||
<p>I incorporated the Fletcher 16 checksum algorithm into the source for security reasons; it might be challenging to make changes without breaking the main functionality of the code.
|
||||
The space after <code>#define p return</code> is necessary.</p>
|
||||
|
||||
<p>The computus uses an algorithm described in the journal Nature in 1876. It should be valid for Gregorian calendars.</p>
|
||||
|
||||
<h4>Some obfuscation techniques used</h4>
|
||||
|
||||
<ol>
|
||||
<li>I tried to use meaningless or misleading variable names. For example, this program draws the Big Dipper with the correct colors, but variables
|
||||
like <code>o</code>, <code>b</code>, and <code>a</code> are used in totally unrelated tasks.</li>
|
||||
<li>I reused and recycled variables almost every time when possible.</li>
|
||||
<li>Unnecessary use of predefined stuff like <code>__ATOMIC_SEQ_CST</code>.</li>
|
||||
<li>When I was a kid, my favorite programming language was Pascal. In Pascal, there are things like <code>begin;</code> and <code>end;</code> instead of curly brackets.
|
||||
They are used also in my code, but I had to shorten them to meet size requirements.</li>
|
||||
<li>I also have strong Perl background,
|
||||
and therefore I added some dollar signs to the code. One of the first ideas was to
|
||||
write all variables with prefixed <code>$</code>, but then I rejected it.</li>
|
||||
</ol>
|
||||
|
||||
|
||||
<p>If you think you understand how this program works, can you answer these questions:</p>
|
||||
|
||||
<ol>
|
||||
<li>What is the value of <code>aI_</code> after line 21?</li>
|
||||
<li>Why are there some big numbers on line 47?</li>
|
||||
<li>How is the scaling effect created?</li>
|
||||
<li>How do you change a single bit, without changing the functionality?</li>
|
||||
</ol>
|
||||
|
||||
|
||||
<h3>Rot18ed part</h3>
|
||||
|
||||
<p>Because the rot13 is too easy to decode with the plain eyes, I decided to use the Caesar cipher with the key 18.</p>
|
||||
|
||||
<p>Lzw xajkl tsffwj ak wfugvwv mkafy AWWW 754 xdgslk gf dafw 47. Al ak hjaflwv gfdq gf dalldw-wfvasf esuzafwk.</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<TABLE><TR>
|
||||
<TD><a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/3.0/88x31.png" /></a></TD>
|
||||
<TD><P>© Copyright 1984-2018,
|
||||
<A HREF="/judges.html">Leo Broukhis, Simon Cooper, Landon Curt Noll</A>
|
||||
- All rights reserved<BR>
|
||||
This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
|
||||
<TD> <!--<a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
|
||||
</TR></TABLE>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,227 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="GENERATOR" content="mkd2html 2.1.5a DL=DISCOUNT">
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
|
||||
<link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="../hint.css">
|
||||
<title>Most connected</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Most connected</h1>
|
||||
|
||||
<p>Scott Vokes<br>
|
||||
Twitter: @silentbicycle</p>
|
||||
|
||||
<h2>Judges' comments:</h2>
|
||||
|
||||
<h3>To use:</h3>
|
||||
|
||||
<pre><code>make
|
||||
./prog < example-1.txt
|
||||
</code></pre>
|
||||
|
||||
<h3>Try:</h3>
|
||||
|
||||
<pre><code>./prog < example-2.txt
|
||||
./prog < example-tab.txt
|
||||
./prog < ioccc.txt
|
||||
</code></pre>
|
||||
|
||||
<h3>Selected Judges Remarks:</h3>
|
||||
|
||||
<p>What this program does is not witchcraft and there are no spectres, but you
|
||||
might have a meltdown trying to work it all out.</p>
|
||||
|
||||
<p>This entry is designed to mislead in many ways. However, if you find yourself
|
||||
wanting to know the possibilities for navigating a graph, you will get the
|
||||
answer you seek with no hocus pocus.</p>
|
||||
|
||||
<h2>Author’s comments:</h2>
|
||||
|
||||
<h2>Introduction</h2>
|
||||
|
||||
<p>This program reads a directed graph (as lines with integer node IDs),
|
||||
and prints the graph’s nodes in reverse-topologically sorted order,
|
||||
grouped into strongly connected components. Given a set of nodes
|
||||
representing targets and edges representing dependencies between them,
|
||||
it produces a build order with any dependency cycles gathered.</p>
|
||||
|
||||
<p>For example, the following input (provided as <code>example-1.txt</code>):</p>
|
||||
|
||||
<pre><code>0 4 8
|
||||
1 0
|
||||
2 1 3
|
||||
3 2
|
||||
4 1
|
||||
5 4 6
|
||||
6 5 2
|
||||
7 3 6 7
|
||||
</code></pre>
|
||||
|
||||
<p>would be interpreted as:</p>
|
||||
|
||||
<pre><code>0 -> 4, 8
|
||||
1 -> 0
|
||||
2 -> 1, 3
|
||||
3 -> 2
|
||||
4 -> 1
|
||||
5 -> 4, 6
|
||||
6 -> 5, 2
|
||||
7 -> 3, 6, 7
|
||||
</code></pre>
|
||||
|
||||
<p>So, node 0 has edges to / depends on nodes 4 and 8, node 1 depends on
|
||||
node 0, and so on. Then, it groups the graph’s nodes into
|
||||
strongly connected components and prints them in reverse-topologically
|
||||
sorted order:</p>
|
||||
|
||||
<pre><code>0: 8
|
||||
1: 0 1 4
|
||||
2: 2 3
|
||||
3: 5 6
|
||||
4: 7
|
||||
</code></pre>
|
||||
|
||||
<p>It uses Tarjan’s strongly connected components algorithm for the
|
||||
grouping and reverse-topological sorting, along with a bonus hidden
|
||||
implementation of counting sort, which sorts each group.</p>
|
||||
|
||||
<p>For other details about the input format, see “Issues and
|
||||
Limitations”.</p>
|
||||
|
||||
<h2>Building</h2>
|
||||
|
||||
<p>To build:</p>
|
||||
|
||||
<pre><code>${CC} -o prog prog.c -std=c11 -O3 \
|
||||
-Wall -Wextra -pedantic -Wno-missing-prototypes
|
||||
</code></pre>
|
||||
|
||||
<p><code>-Wno-missing-prototypes</code> is necessary because there aren’t any
|
||||
prototypes. (They would put the program well over the size limit.)</p>
|
||||
|
||||
<p>Note: The program can also be built with <code>-std=c99</code> or <code>-std=c89</code>.</p>
|
||||
|
||||
<p>If building with <code>-Weverything</code>, then <code>-Wno-strict-prototypes</code>
|
||||
may also be necessary – the function pointer declarations for
|
||||
<code>_</code> and <code>B</code> may get warnings otherwise, for reasons described
|
||||
under “Obfuscations”.</p>
|
||||
|
||||
<h2>Obfuscations</h2>
|
||||
|
||||
<ul>
|
||||
<li><p>This entry uses functions that have a variable number of arguments,
|
||||
but despite what the rules say, there is no need to be careful about
|
||||
<code>va_list</code> implementation differences. :) . There are several
|
||||
references to a function pointer, <code>_</code>, but it’s called with different
|
||||
numbers of arguments in different places. (In particular, look at
|
||||
<code>spell</code>.) Because the function pointer declaration has an empty list
|
||||
of parameters, the argument count and types are unconstrained. <code>_</code> is
|
||||
set to different functions in several places, but it is always called
|
||||
with appropriate argument(s) for its possible current functions. This
|
||||
is allowed by the standard – The section on F,I,N,D,M,Y,C,L,U,E has
|
||||
further details.</p></li>
|
||||
<li><p>It uses <code>_</code> in three different scopes: as a goto label (function
|
||||
scope), as an enum name, and a <code>_</code> function pointer (which is required
|
||||
to have file scope, since it starts with ‘_’). There are also other
|
||||
<code>_</code>s: it appears in a string, obscured by a headecimal escape sequence
|
||||
(<code>\x5f</code>), and the cauldron is supported by a giant underscore.
|
||||
(Does this program qualify for Best One Liner?)</p></li>
|
||||
<li><p>Most of the variables are not only global, but used for unrelated
|
||||
purposes at different times, so just renaming them while studying the
|
||||
program should make it even more confusing. The few variables local to
|
||||
functions have their names reused for different things in other
|
||||
functions.</p></li>
|
||||
<li><p>There is an enum early on that defines several single-letter
|
||||
identifiers: F,I,N,D,M,Y,C,L,U,E. These are used for array offsets,
|
||||
both individually and in combination. The first several values are
|
||||
also a clue: ISO/IEC 9899:1999 chapter 6.7.5.3 verse 14 describes how
|
||||
function declarators with an empty parameter list behave. (As does
|
||||
3.5.4.3 for ANSI C, which explains the 0x3543 that appears soon
|
||||
after.)</p></li>
|
||||
<li><p>Several parts of the program’s state are stashed in otherwise unused
|
||||
offsets of the node arrays. These locations are accessed in multiple
|
||||
ways, such as using <code>I[p]</code> (where I == 7) as well as <code>p[F+L]</code> (6+1),
|
||||
or <code>b[M-N]</code> (14-5) and <code>U[b]</code> (where U == 9).</p></li>
|
||||
<li><p>The other identifiers are misleading, punny, or both. <code>spectre</code> does
|
||||
not exploit CVE-2017-5753 or CVE-2017-5715, for example – it just fits
|
||||
the witch theme. <code>cast</code> doesn’t cast, <code>hex</code> has nothing to do with
|
||||
hexadecimal, <code>bubble</code> is not bubble sort, there is no undefined
|
||||
behavior in <code>nasal_demons</code>, and <code>main</code> has absolutely nothing to do
|
||||
with a hand.</p></li>
|
||||
<li><p>For well-formed input, how the program determines when to exit is a
|
||||
bit obscure. <code>main</code> ends with a <code>goto</code> leading back to an earlier <code>_</code>
|
||||
label, so it just loops forever, and <code>exit</code> only appears in code paths
|
||||
related to error-handling. It looks like <code>cast</code> calls <code>meltdown</code> with
|
||||
its second argument set to 0, which would call <code>exit</code>, but running in
|
||||
gdb with a breakpoint on <code>cast</code> reveals that it isn’t being called…</p></li>
|
||||
<li><p>Instead of using <code>isdigit()</code>, the program checks the numeric value of
|
||||
each <code>char</code>, and literals that would suggest comparing against e.g. ‘0’
|
||||
are specified in octal in one place, and produced by arithmetic using
|
||||
the enum elsewhere.</p></li>
|
||||
<li><p>Common conventions are subverted: <code>i</code> is not a loop index, <code>argv</code> and
|
||||
<code>argc</code>’s names are swapped.</p></li>
|
||||
<li><p><code>NULL</code> does not appear in the program. Instead, <code>argc[argv]</code> (which is
|
||||
required to be a null pointer) is saved and passed to where its value
|
||||
is needed.</p></li>
|
||||
<li><p>Oh, and the program is squashed into the shape of a bubbling cauldron,
|
||||
on top of a giant underscore, so there’s that.</p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Issues and Limitations</h2>
|
||||
|
||||
<ul>
|
||||
<li><p>Despite appearances, it does not handle numbers in hex, or provide
|
||||
a <code>curses(3)</code>-based interface.</p></li>
|
||||
<li><p>The expected input format is zero or more lines of space-separated
|
||||
integers. If other characters appear in the input, it will either
|
||||
reject the input entirely and exit with a non-zero status, or skip
|
||||
number(s) adjacent to the non-digit characters, depending on where the
|
||||
characters appear. Tabs and multiple consecutive spaces are handled
|
||||
correctly, however.</p></li>
|
||||
<li><p>Individual lines of input longer than <code>0x3543 - 1</code> bytes will be
|
||||
split and processed as if they were multiple lines of input, which can
|
||||
produce incorrect results. This magic number’s significance is
|
||||
described earlier.</p></li>
|
||||
<li><p>The algorithm expects its input to represent a fully connected graph.
|
||||
While the output is otherwise topologically sorted, if there are nodes
|
||||
completely unconnected to the rest of the graph (with or without
|
||||
self-cycles), they will be output as soon as they are processed –
|
||||
this means that, when there are disconnected nodes, reordering the
|
||||
input lines can produce different output. Addressing this by adding
|
||||
another pass is would put the program over the size limit.</p></li>
|
||||
<li><p>While the node IDs don’t need to be consecutive or start at 0, the
|
||||
implementation doesn’t have special handling for sparse graphs. If you
|
||||
give it a graph with nodes numbered 0 and 2147483647, it will attempt
|
||||
to allocate sufficient memory (potentially around 32 GB) for the
|
||||
entire range of graph nodes, even if those are the only ones. If
|
||||
memory allocation returns NULL, it will gracefully exit, otherwise it
|
||||
will succeed, eventually, perhaps after a great deal of swapping.</p></li>
|
||||
<li><p>Node IDs >= 2147483648 will cause the program to print an error
|
||||
message and exit with a non-zero status. This shrinks the code that
|
||||
detects overflowing the array size by a bit.</p></li>
|
||||
<li><p>A very large group of nodes in a cycle can cause a stack overflow.
|
||||
This typically takes over 100,000 nodes, and depends on the order the
|
||||
nodes are visited. Addressing this would put the program over the size
|
||||
limit.</p></li>
|
||||
<li><p>The implementation depends on the characters ‘0’, ‘1’, … ‘9’ having
|
||||
the values 48 through 57, rather than using <code>isdigit()</code>. As noted
|
||||
above, this program has nothing to do with a hand.</p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
<TABLE><TR>
|
||||
<TD><a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/3.0/88x31.png" /></a></TD>
|
||||
<TD><P>© Copyright 1984-2018,
|
||||
<A HREF="/judges.html">Leo Broukhis, Simon Cooper, Landon Curt Noll</A>
|
||||
- All rights reserved<BR>
|
||||
This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
|
||||
<TD> <!--<a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
|
||||
</TR></TABLE>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,189 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="GENERATOR" content="mkd2html 2.1.5a DL=DISCOUNT">
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
|
||||
<link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="../hint.css">
|
||||
<title>Most shifty</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Most shifty</h1>
|
||||
|
||||
<p>Don Yang<br>
|
||||
<a href="http://uguu.org/">http://uguu.org/</a></p>
|
||||
|
||||
<h2>Judges' comments:</h2>
|
||||
|
||||
<h3>To use:</h3>
|
||||
|
||||
<pre><code>make
|
||||
more generated1.c
|
||||
more generated2.c
|
||||
more generated3.c
|
||||
</code></pre>
|
||||
|
||||
<h3>Try:</h3>
|
||||
|
||||
<pre><code>make
|
||||
./left < prog.c
|
||||
./right < prog.c
|
||||
./left < prog.c | ./left
|
||||
|
||||
./shift < prog.c
|
||||
|
||||
./msg0
|
||||
./msg1
|
||||
./msg2
|
||||
</code></pre>
|
||||
|
||||
<h3>Selected Judges Remarks:</h3>
|
||||
|
||||
<p>Code should be readable in any direction! This tool will help you rotate your
|
||||
code so you don’t have to stare at it sideways or even upside down. Rotating
|
||||
this program left and recompiling will reveal other tools including a right rotate
|
||||
and a shift program.</p>
|
||||
|
||||
<p>Strange things happen when the world is upside down! It is entirely possible
|
||||
that this is remark is completely misleading.</p>
|
||||
|
||||
<p>What exactly does the shift program do?</p>
|
||||
|
||||
<p>Like a great sliding puzzle (hint) this entry has 6 more programs that will
|
||||
reveal messages and one more tool that can be used to reveal the final
|
||||
message hidden in the original source. All of these can be created using
|
||||
combinations of ./left, ./right and ./shift and the additionally generated
|
||||
programs.</p>
|
||||
|
||||
<p>The final message can be revealed using</p>
|
||||
|
||||
<pre><code>./msg9 < prog.c
|
||||
</code></pre>
|
||||
|
||||
<p>But what combinations will generate ./msg3, ./msg4, ./msg5, ./msg6, ./msg7,
|
||||
./msg8 and finally ./msg9?</p>
|
||||
|
||||
<h2>Author’s comments:</h2>
|
||||
|
||||
<h1>Tools usage</h1>
|
||||
|
||||
<p>Nuko is a text rotator: given some text in stdin, Nuko will write the
|
||||
same text to stdout, but rotated 90 degrees counterclockwise.</p>
|
||||
|
||||
<pre><code>gcc prog.c -o left
|
||||
./left < input.txt > rotated_counterclockwise.txt
|
||||
</code></pre>
|
||||
|
||||
<p>Due to static memory allocation, only the first 1K columns by 1K rows
|
||||
are rotated, the rest are silently ignored. But fear not, a separate
|
||||
tool with dynamic memory allocation is included:</p>
|
||||
|
||||
<pre><code>./left < prog.c > r1.c
|
||||
gcc r1.c -o right
|
||||
./right < input.txt > rotated_clockwise.txt
|
||||
</code></pre>
|
||||
|
||||
<p>For variety, this second tool rotates clockwise instead of
|
||||
counterclockwise. Also, it can handle files larger than 1024x1024,
|
||||
depending on how much memory you got.</p>
|
||||
|
||||
<p>Of course we wouldn’t stop with just two rotations, if we continue to
|
||||
rotate counterclockwise once more, we get another program. This
|
||||
program outputs a single message to stdout, which is the name of the
|
||||
series that Nuko came from.</p>
|
||||
|
||||
<pre><code>./left < prog.c | ./left > r2.c
|
||||
gcc r2.c -o msg0
|
||||
./msg0
|
||||
</code></pre>
|
||||
|
||||
<p>There is one final rotation, which produces a tool that removes
|
||||
leading whitespaces:</p>
|
||||
|
||||
<pre><code>./left < prog.c | ./left | ./left > r3.c
|
||||
gcc r3.c -o shift
|
||||
./shift < input.txt > no_leading_space.txt
|
||||
</code></pre>
|
||||
|
||||
<p>Where this might be useful, besides ruining the formatting of certain
|
||||
files, is that it completes the set of tools needed to solve the
|
||||
puzzle that is embedded in prog.c</p>
|
||||
|
||||
<h1>Puzzle box</h1>
|
||||
|
||||
<p>Notice how the edges of prog.c contain two notches. By rotating
|
||||
prog.c and removing leading space, the code would be shifted one space
|
||||
toward one of those notches (and creating a new notch on the other
|
||||
side). This shifted code behaves slightly different from the original
|
||||
program. For example, here are two more messages that can be
|
||||
produced:</p>
|
||||
|
||||
<pre><code>./shift < prog.c | ./right > msg1.c && gcc msg1.c -o msg1 && ./msg1
|
||||
./shift < prog.c | ./left > msg2.c && gcc msg2.c -o msg2 && ./msg2
|
||||
</code></pre>
|
||||
|
||||
<p>In total, there are 9 embedded strings that can be produced via a
|
||||
sequence of rotates and shifts, one of which can be used to extract
|
||||
the 10th final string from prog.c. The intent is to simulate those
|
||||
wooden puzzle boxes that can be opened by pushing and shifting various
|
||||
well-concealed seams. Thus, finding the correct sequence of rotates
|
||||
and shifts is left as an exercise to the reader (but if you are really
|
||||
lazy, just read the Makefile).</p>
|
||||
|
||||
<p>Source code for all the tools needed to solve this puzzle are embedded
|
||||
in prog.c, all you need is a C compiler.</p>
|
||||
|
||||
<h1>Features</h1>
|
||||
|
||||
<ul>
|
||||
<li><p> Code compiles when rotated 4 ways. This required a bit of
|
||||
patience to achieve. Code still compiles even with one column of
|
||||
text shifted. This required even more patience.</p></li>
|
||||
<li><p> All rotated and shifted variants compiles without warnings. This
|
||||
involves various tweaks to satisfy cases where compiler is overly
|
||||
protective, including but not limited to the “1125” at line 4 as
|
||||
opposed to “1025”, to satisfy -Waggresive-loop-optimizations.</p></li>
|
||||
<li><p> CRC32 of the code is embedded in the code itself.</p></li>
|
||||
<li><p> Process for writing prog.c is available in spoiler.html</p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h1>Compatibility</h1>
|
||||
|
||||
<p>Nuko and the rotated tools accepts only ASCII files where each
|
||||
character maps to exactly one byte. Also, end-of-line sequence is
|
||||
assumed to be LF only, as opposed to CR-LF. All control characters
|
||||
are treated like normal printable characters, so files containing tabs
|
||||
will look weird after rotation, for example.</p>
|
||||
|
||||
<p>Nuko has been verified to work with these compiler / OS combinations:</p>
|
||||
|
||||
<ul>
|
||||
<li> gcc 4.8.4 on Linux</li>
|
||||
<li> gcc 4.9.2 on Linux</li>
|
||||
<li> gcc 6.1.0 on JS/Linux</li>
|
||||
<li> gcc 6.3.0 on Linux</li>
|
||||
<li> gcc 6.4.0 on Cygwin</li>
|
||||
<li> clang 3.5.0 on Linux</li>
|
||||
<li> clang 3.8.1 on Linux</li>
|
||||
<li> clang 5.0.1 on Cygwin</li>
|
||||
<li> tcc 0.9.25 on JS/Linux</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>Nuko compiles without warnings with all compilers above, even with
|
||||
“-Wall -Wextra -pedantic” for gcc and clang.</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<TABLE><TR>
|
||||
<TD><a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/3.0/88x31.png" /></a></TD>
|
||||
<TD><P>© Copyright 1984-2018,
|
||||
<A HREF="/judges.html">Leo Broukhis, Simon Cooper, Landon Curt Noll</A>
|
||||
- All rights reserved<BR>
|
||||
This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
|
||||
<TD> <!--<a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
|
||||
</TR></TABLE>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user