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:
Cody Boone Ferguson committed 2023-02-08 05:07:05 -08:00
1 parent ee8a36310f
commit 77fb0f11a2
143 files changed
-28606

No files matched your search

-273
View File
@@ -1,273 +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.2.0">
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8"> <link rel="stylesheet"
type="text/css"
href="../hint.css">
<title>Most functional interpreter</title>
</head>
<body>
<h1>Most functional interpreter</h1>
<p>Ondřej Adamovský <a href="&#x6d;&#x61;&#x69;&#108;&#x74;&#111;&#58;&#111;&#97;&#64;&#99;&#109;&#x61;&#x69;&#x6c;&#x2e;&#x63;&#x7a;">&#111;&#x61;&#64;&#x63;&#x6d;&#x61;&#x69;&#x6c;&#46;&#x63;&#x7a;</a></p>
<h2>Judges' comments:</h2>
<h3>To use:</h3>
<pre><code>make prog
./prog file.unl
</code></pre>
<h3>Try:</h3>
<pre><code>./prog spam.unl
./prog sierpinski.unl | less
./prog advent.unl
</code></pre>
<h3>Selected Judges Remarks:</h3>
<p>Even after pre-processing and indenting, the C code of this entry
is about as understandable as the Unlambda code.</p>
<p>Pretending that we don&rsquo;t know a bit of functional programming :) and lacking a better way
to understand the entry but to fuzz it,
we stumbled on a string of bytes which crashed it:</p>
<pre><code>````.0`.0`.0`c.0``sssss
</code></pre>
<p>Functional programming is not a panacea against core dumps, after all.</p>
<h2>Author&rsquo;s comments:</h2>
<p><strong>&#187;A highly structured state state machine&#171;</strong></p>
<h3>Purpose</h3>
<p>The purpose of this program is to allow you to play Colossal Cave Adventure as
implemented by <a href="https://github.com/irori/advent-unlambda" title="Adventure">Kunihiko Sakamoto</a>. As that was written in <a href="http://www.madore.org/~david/programs/unlambda/" title="Unlambda programming language">Unlambda programming
language</a> designed by David Alexander Madore it has to be an Unlambda interpreter.</p>
<h3>Aesthetics</h3>
<p>The program grew a bit too long so I had to use several macros to downsize it.
That unfortunately reduced my options for program layout. I decided to separate
it into two portions. The initial macro section where I had limited resources and
you should disregard its shape, unless you like it, and the rest is a separator in the
form of a single line followed by a section signifying the function of the program,
a block with removed shape of lambda character. Even the official IOCCC size tool
acknowledges this: When you call <code>./iocccsize -i &lt;prog.c</code>, using the
<a href="/2019/iocccsize.c">2019 version of iocccsize</a>,
iocccsize returns <strong>955</strong>, which is the Unicode codepoint of the <strong>&#955;</strong> character.</p>
<p>It might be a surprise for you that according to the IOCCC size tool the program is
actually a <em>oneliner</em>. It certainly was for me. I like to think the tool is overwhelmed
by the sheer length of the dividing line and totally overlooks the rest of the program.</p>
<h3>Usage</h3>
<p>When built directly</p>
<pre><code>make
</code></pre>
<p>the program (<em>prog</em>) accepts a single parameter with the name of an Unlambda program. You can
download the <a href="https://github.com/irori/advent-unlambda" title="Adventure">Colossal Cave Adventure</a> (the <em>advent.unl</em> file) and run it like this</p>
<pre><code>./prog advent.unl
</code></pre>
<p>You can also try other programs from the Web. Many example programs are in the official
<a href="http://www.madore.org/~david/programs/unlambda/#distrib" title="Reference Unlambda distribution">Unlambda distribution</a> on the Unlambda homepage. The most complex programs there are
entries from <a href="http://www.madore.org/~david/programs/unlambda/#quine" title="Unlambda quine contest">quine contest</a>.</p>
<p>There is an alternative build path that requires IOCCC size tool to complete. Put the tool
source <em>iocccsize.c</em> in the project directory and call</p>
<pre><code>make identify
</code></pre>
<p>It will build the tool and use it to build an alternative program <em>prog2</em>, which in turn will
produce an Unlambda program <em>identify.unl</em>. <code>make identify</code> runs this program to identify
itself.</p>
<p>The base program (<em>prog</em>) implements an interpreter of Unlambda 2.0. It recognises all its
builtins (k, s, i, v, c, d, .<em>x</em>, e, @, ?<em>x</em> and |) including the syntactic sugar function
(&#8203;r&#8203;) and formating properties in the form of ignoring whitespace and comments
to the end of line introduced by the <em>#</em> character.</p>
<p>In case of wrong usage (missing Unlambda program file or missing parameter) or use of an unseekable
Unlambda program source if it uses the <em>c</em> function, the program returns message <em>fail</em>. It
also informs you about syntactic errors in the Unlambda program should there be any (but only
when the execution reaches them).</p>
<p>The Unlambda source file may contain several Unlambda programs. The interpreter will run
them all in sequence.</p>
<h3>Unlambda</h3>
<p>If you want to familiarise yourself with the language, visit its <a href="https://en.wikipedia.org/wiki/Unlambda" title="Unlambda on Wikipedia">Wikipedia page</a> for
a brief introduction or its <a href="http://www.madore.org/~david/programs/unlambda/" title="Unlambda programming language">homepage</a> for an indepth discussion. For further reading you
can visit Wikipedia pages on <a href="https://en.wikipedia.org/wiki/Lambda_calculus" title="Lambda Calculus on Wikipedia">Lambda Calculus</a> and <a href="https://en.wikipedia.org/wiki/Combinatory_logic" title="Combinatory Logic on Wikipedia">Combinatory Logic</a>.</p>
<p>You can also play with an <a href="https://inazz.jp/unlambda/" title="Online Unlambda interpreter">online interpreter</a> by Github user inazz. There you can
debug one of example programs provided or try your wits in writing your own.</p>
<h3>Hints</h3>
<p>Here are some pointers where to start when trying to understand the interpreter:</p>
<ul>
<li>Where is syntax error detected?</li>
<li>How is the memory managed?</li>
<li>How does a program character turn into a function?</li>
<li>How does exit function <em>e</em> work?</li>
<li>Can fD0 function be called?</li>
<li>Are the function names familiar? (warning: some are misleading)</li>
</ul>
<h3>Obfuscation sources</h3>
<ul>
<li>The elephant in the room is the Unlambda language. As we all know, functional
programming defies sanity. Furthermore, Unlambda was specifically designed
to be unintelligible and hard to code in. Most of its functions are quite
simple and straightforward to implement, but two make it a mess: the promise
operator <em>d</em> and the call with current continuation <em>c</em>.</li>
<li>Most of the additional obfuscation is derived from basic design choices. That
is, how the state of the program is stored and how are the Unlambda functions
implemented.</li>
</ul>
<p>More on this in the Spoilers section.</p>
<h3>Build notes</h3>
<p>The program does not require any special treatment by compilers. Some warnings
had to be suppressed when compiling with <code>-Wall -Wextra -pedantic</code>. Those were
produced because of the formatting of the source code, not any programming
technique. Compilation with <code>-Weverything</code> produced many more warnings, but those
are only relevant for multi-source-file projects and some are really questionable
(e.g. <code>-Wdisabled-macro-expansion</code>).</p>
<h3>Portability</h3>
<p>Development was done on Debian 9 on x86-64 architecture using mainly Clang 3.8.1-24
and GCC 6.3.0. The source is C11 compliant and does not use any special properties
except the following:</p>
<ul>
<li>The interpreter sort of relies on tail call optimization. It works well even
without it, but the stack runs out quickly with some Unlambda programs (e.g. <em>trivial.unl</em>
example from the <a href="http://www.madore.org/~david/programs/unlambda/#distrib" title="Reference Unlambda distribution">reference Unlambda distribution</a> produces segfault).
Clang with <code>-O3</code> option does this optimization well and said example does
not segfault with it. I was not able to force GCC to optimize it out (probably
an operator fault).</li>
<li>The only data structure of the program (the union structure) had much more
members originally. I joined all integers to a single long long member in the name
of obfuscation. It is used for reference counting (only 1 for every reference) among
other uses. size_t should be used for that, but practically, I think the memory
would run out sooner than the reference counter in any real world situation
even when size_t is bigger than long long. It is also used for storing chars
for later printing. This might produce some warnings, but since it was developed
using chars it should be always used safely.</li>
</ul>
<h3>Spoilers</h3>
<ul>
<li><p>You can examine the <em>progSpoiler.c</em> file. It is the original final version of
the interpreter, before I started the downsizing. It accepts one more optional
parameter that specifies filename for the output Unlambda function (it&rsquo;s the
Unlambda function, that remains after all function applications are done).
When no filename is provided, <em>stderr</em> is used.</p>
<p>The function <em>output</em> is used for this additional functionality. You can use
it while debugging to visualise current variables.</p></li>
<li><p>The Unlambda functions are represented by a record consisting of an array of five
multipurpose arguments. The first one refers to the function implementing its
application, the second and the third ones are for arguments of the function,
the fourth one is for stack building, and the fifth one is the reference counter.</p>
<p>The function argument is used not only for evaluation of the functions, but also
as a state variable to decide whether we want to call it, or do something else.</p></li>
<li><p>The interpreter reads the Unlambda source as it interprets it, translating
the incoming character to a function using a constructor stored in translation array <em>T</em>.</p>
<p>This means the interpreter must reposition in the source file whenever current
continuation is called.</p></li>
<li><p>The state of the interpreter is represented by trees representing evaluated
Unlambda functions stored on the C stack as local variables, plus the source file
position. When a current continuation is created, the stack is unwound using the
fourth argument of the nodes, stored in the continuation, and rebuilt back resuming
the evaluation. When its called, the stack is unwound and thrown away, and the
stack stored in the continuation is restored.</p>
<p>This makes implementation of a complete debugger a bit more challenging.</p>
<p>For this to work, the functions that do the work (i.e. make series of applications
and/or evaluations each of which may be a call to current continuation), the <em>s</em>
combinator and the <em>`</em> application operation had to be broken down to pieces, one
for each application/evaluation and corresponding helper functions for stack
rebuilding. (the helper functions are named beginning with <em>r</em> instead of <em>f</em>)</p></li>
<li><p>The <em>`</em> application operation does the reading of the Unlambda source when needed. It
also implements the promise function. Whenever it would apply it, it overwrites
the Apply constructor in translation array <em>T</em>, changing its function to build
unevaluated subtree that is later evaluated whenever the promise is applied.</p></li>
<li><p>To further the obfuscation, I shortened the function names while downsizing,
but preserved their meaning (with the exception of Apply functions, which I
renamed to Y to possibly confuse with Y combinator). Simple functions retained
their names to misguide the reader to believe to know what is what. The names
of continuation and exit functions were swapped. The names of S and Apply
functions were shuffled both for S functions and Apply functions in the same way
to hide the meaning of <em>f</em> and <em>r</em> prefixes.</p></li>
</ul>
<h3>Identification spoiler</h3>
<p>The alternative build path <code>make identify</code> output commemorates a <a href="http://ioccc.org/2014/birken/hint.html" title="Best use of port 1701">previous IOCCC winner</a> which uses
similar methods to mess with the size tool.</p>
<h3>Judges remarks spoilers</h3>
<p>It is not a bug, it is a feature. :)</p>
<p>The crash is caused by a stack overflow. Conventional Unlabmda interpreters implement
the Unlambda execution stack using data structures on the heap. This interpreter uses
the C call stack for this purpose. In a conventional interpreter, the judges program would
consume memory until the user (or the operating system) would lose patience. The C call stack
is usually of a limited size and protected, so this interpreter crashes, when the judges
program depletes the stack. You can always increase the maximal stack size through
the system settings (on Linux) or compiler options (on Windows) if your Unlambda program
needs it. Nevertheless, it will not help the judges program which quickly depletes any limit
you define.</p>
<p>The judges, pretending not to know what they are doing, created a program that grows
Unlambda execution stack indefinitely. You may consider it an Unlambda antipattern.
Normally, infinite cycles in Unlambda work by creating two functions and applying one
to the other which creates further functions to apply. The application of the function
frees its position on the stack. This program builds one ever growing function that will
never be complete and able to be applied.</p>
<hr />
<TABLE><TR>
<TD><a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="/png/by-sa-3.0-88x31.png" /></a></TD>
<TD><P>&copy; Copyright 1984-2019,
<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="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
<TD>&nbsp;<!--<a href="https://validator.w3.org/check?uri=referer"><img src="https://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
</TR></TABLE>
</body>
</html>
-101
View File
@@ -1,101 +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.2.0">
<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</p>
<h2>Judges' comments:</h2>
<h3>To use:</h3>
<pre><code>make
</code></pre>
<h3>Try:</h3>
<pre><code>./prog &lt; prog.c
</code></pre>
<h3>Selected Judges Remarks:</h3>
<p>A tiny, but punctually correct way of POSIX counting for text files. This one
line, one word, 127 character beauty continues to expand the number of classic
unix utilities available as winning entries.</p>
<h2>Author&rsquo;s comments:</h2>
<h2>Synopsis</h2>
<p>Feed it anything on stdin. <br>
The output should look familiar.</p>
<p>Compiles cleanly with:</p>
<pre><code>WARN="-Wno-implicit-int -Wno-missing-variable-declarations -Wno-parentheses"
clang -Wall -Wextra -Weverything -pedantic $WARN -include stdio.h -o prog prog.c
</code></pre>
<h2>Description</h2>
<p>Included is a test script, useful for the corner cases.
As in all good Unix programs, it is silent upon success; any output demonstrates an error.
Instead of checking correctness, the check script can simply output the results: <br>
(The Makefile contains the spoiler):</p>
<pre><code>out=cat ./check ./prog
</code></pre>
<p>Interestingly, and a spoiler here: MacOS and FreeBSD implement the common utility &ldquo;correctly&rdquo;.
Centos and Ubuntu both share a &ldquo;flawed&rdquo; utility that changes output format based upon input redirection or pipeline(!).
As well, the latter two also behave slightly differently on what they count as whitespace:
\a and \b are both counted whitespace(!), even though the relevant man pages on these systems
omit these characters from the description.</p>
<p>This program follows FreeBSD and MacOS, the arbiters of correct for these purposes.</p>
<h2>Limits</h2>
<p>Requires the C locale and ASCII character set. <br>
Input should be less than ten million octets toavoidthisproblem.</p>
<h2>See Also</h2>
<p>You can enjoy this code from beginning to end. <br>
No whitespace was harmed in the creation of this program. <br>
All your base belong to us, but the constants seem a bit &hellip; off?</p>
<h2>Bonus</h2>
<p>The script <code>cow</code> provides a closer analog, and perhaps a more useful interface.</p>
<p>Included is a version without compilation warnings:</p>
<pre><code>clang -Wall -Wextra -Weverything -pedantic -include stdio.h -o prog.clean prog.clean.c
</code></pre>
<h2>Bugs</h2>
<p>The flags are not supported. Although they could easily be added into <code>cow</code>.
This exercise left to the reader.</p>
<hr />
<TABLE><TR>
<TD><a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="/png/by-sa-3.0-88x31.png" /></a></TD>
<TD><P>&copy; Copyright 1984-2019,
<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="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
<TD>&nbsp;<!--<a href="https://validator.w3.org/check?uri=referer"><img src="https://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
</TR></TABLE>
</body>
</html>
-183
View File
@@ -1,183 +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.2.0">
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8"> <link rel="stylesheet"
type="text/css"
href="../hint.css">
<title>Most alphabetic</title>
</head>
<body>
<h1>Most alphabetic</h1>
<p>Marcin Ciura<br>
Twitter: @mciura</p>
<h2>Judges' comments:</h2>
<h3>To use:</h3>
<pre><code>make
./getwords.sh en | grep .. | ./prog aeiouvwxyz
</code></pre>
<h3>Try:</h3>
<pre><code>./getwords.sh en | grep .. | ./prog aeiouhjklmnvwxyz
./getwords.sh en | grep .. | ./prog mrjocktvquizphdbagsfewlynx
./en.sh
./fr.sh
./ru.sh
</code></pre>
<h3>Selected Judges Remarks:</h3>
<p>A few letters, one at a time, with no repeats.
How many different ways can this be done?</p>
<p>While a quick brown fox might jump over the lazy dog,
it has too many repeat letters to allow this entry to repeat.
It is better that Mr Jock, TV quiz PhD, bags few lynx.</p>
<p>Speaking of jumping, can you rewrite the code to
remote all of the goto jumps in this code?</p>
<h2>Author&rsquo;s comments:</h2>
<h3>What is this? <a name="wit"></a></h3>
<p>This entry reads from standard input a list of words in any language
written with an alphabet and outputs perfect pangrams composed of these
words. A perfect pangram is a series of words that contains every letter
of the alphabet exactly once.</p>
<p>Example execution:</p>
<pre><code>$ grep .. /usr/share/dict/words | ./prog abcdefghijklmnopqrstuvwxyz
qualm fjord wiz pyx vs beg kc nth
quartz jinx vs fed kc womb glyph
quid jamb fez vs pyx kc growl nth
quiz fjord pyx vs bag kc mewl nth
quiz fjord pyx vs gab kc mewl nth
quiz fjord pyx vs gem bawl kc nth
quiz fjord pyx vs meg bawl kc nth
quiz fjord vex bawl kc gyp ms nth
quiz jamb flex vs kc gyp word nth
quiz jamb pyx vs kc flog drew nth
quiz jamb pyx vs kc frog lewd nth
quiz jamb pyx vs kc frog weld nth
quiz jamb pyx vs kc golf drew nth
quiz jamb pyx vs kc grew fold nth
quiz jamb pyx vs kc grow nth fled
quiz jamb pyx vs kc growl fed nth
</code></pre>
<p>Rearranging the words into more or less meaningful expressions is the
user&rsquo;s duty.</p>
<p>This entry implements Algorithm X (<em>Exact cover via dancing links</em>)
from Section 7.2.2.1 in fascicle 5C of <em>The Art of Computer
Programming</em> by Donald E. Knuth. As of June 2019, you can download an
incomplete draft of the fascicle from <a href="https://www-cs-faculty.stanford.edu/~knuth/fasc5c.ps.gz">Knuth&rsquo;s
website</a>.</p>
<h3>Usage</h3>
<p><strong><code>prog LETTERS [N]</code></strong>
reads allowed words from standard input and writes perfect pangrams
with at most <em>N</em> words composed of <em>LETTERS</em> to standard output, one
per line. If <em>N</em> is not given, the number of words in the pangrams is
unlimited. The characters in <em>LETTERS</em> must not repeat. The length of
<em>LETTERS</em> must not exceed 97 characters.</p>
<p>The exit status is 0 if no error occurred, 1 if the input word list
is too long, and 2 if the command-line arguments are missing.</p>
<h3>Helper scripts</h3>
<p><strong><code>getwords.sh LANGUAGE_CODE</code></strong>
outputs a sorted list of unique words in a given language, one per
line. It requires <strong><code>aspell</code></strong> with a dictionary for <em>LANGUAGE_CODE</em>.</p>
<p><strong><code>wrapprog.py LETTERS [N]</code></strong>
works similarly to <strong><code>prog LETTERS [N]</code></strong> except that it merges
anagrams before passing them to <strong><code>prog</code></strong> and expands them in
<strong><code>prog</code></strong>&rsquo;s output. This way, it finishes the job faster than
<strong><code>prog</code></strong> when there are millions of perfect pangrams. It requires a
UTF-8 locale.</p>
<p><strong><code>de.sh</code></strong>, <strong><code>en.sh</code></strong>, <strong><code>fr.sh</code></strong>, <strong><code>it.sh</code></strong>, <strong><code>pl.sh</code></strong>,
and <strong><code>ru.sh</code></strong> output German, English, French, Italian, Polish,
and Russian perfect pangrams, respectively. They require a UTF-8
locale.</p>
<h3>Miscellaneous remarks</h3>
<p>I dare submit this entry to categories <em>algorithms</em>,
<em>internationalization</em> (I have not found active use of <strong><code>&lt;wchar.h&gt;</code></strong>
among the programs that won IOCCC in the past), and <em>obscure bugs</em> (see
the questions about Linux core dumps below).</p>
<p>To a casual eye, this entry may look similar to
<a href="/years.html#2005_klausler">2005 klausler</a>.
However, <strong><code>prog</code></strong> is internationalized and way faster. On my machine,
<strong><code>./klausler abcdefghijklmnopqrstuvwxyz</code></strong> printed only 3,965 perfect
pangrams until I killed it after 144 hours running, while the
equivalent
<strong><code>tr A-Z a-z &lt; /usr/share/dict/words | egrep -v '^[^ais]$' | ./prog abcdefghijklmnopqrstuvwxyz | wc -l</code></strong>
finished in 62 minutes, reporting 1,640,569,315 perfect pangrams, and
the example from section <a href="#wit">What is this?</a> finished in 1.35
seconds. On the other hand, <strong><code>prog</code></strong> can only output series of words
with nonrepeating characters, unlike <strong><code>klausler</code></strong>.</p>
<p>In contrast to <strong><code>prog.orig.c</code></strong>, <strong><code>prog.c</code></strong> does not call
<strong><code>fflush(stdout)</code></strong> after outputting each line, thus running faster.
I am grateful to Witold Jarnicki for suggesting this change.
The original <strong><code>prog</code></strong> finished the example above in 100 minutes
instead of 62 minutes.</p>
<p>If your word list contains meaningless one-letter words, pipe
<strong><code>grep .. [FILE]</code></strong> through <strong><code>prog</code></strong> to eliminate the pangrams that
contain them.</p>
<p>According to <strong><code>prog</code></strong> and <strong><code>aspell</code></strong>, some languages, e.g. Spanish,
have no perfect pangrams.</p>
<p>Why does <strong><code>yes | ./prog y</code></strong> hang on Linux? Change <strong><code>static int</code></strong> to
<strong><code>int</code></strong> and <strong><code>static wchar_t</code></strong> to <strong><code>wchar_t</code></strong>, and recompile
<strong><code>prog</code></strong>. Why does <strong><code>yes | ./prog y</code></strong> dump core now? Change the line
<strong><code>#define P 9&lt;&lt;23^1</code></strong> to <strong><code>#define P 9&lt;&lt;23</code></strong> and recompile
<strong><code>prog</code></strong>. Why does <strong><code>yes | ./prog y</code></strong> exit gracefully?</p>
<p>Answer: Nf bs Whar 2019, guhf znavsrfg ohtf va <strong><code>tyvop</code></strong> 2.22&ndash;2.29:
<a href="https://sourceware.org/bugzilla/show_bug.cgi?id=20568">1</a> naq
<a href="https://sourceware.org/bugzilla/show_bug.cgi?id=20632">2</a>.</p>
<p>The source code uses <strong><code>goto</code></strong> three times. While it could easily get
by without <strong><code>goto M</code></strong> and <strong><code>goto H</code></strong>, I challenge the adherents of
structured programming to refactor <strong><code>goto T</code></strong>, which jumps back into a
nested <strong><code>if</code></strong> block.</p>
<p>With the supplied <strong><code>Makefile</code></strong>, both <strong><code>gcc</code></strong> and <strong><code>clang</code></strong> compile
<strong><code>prog.c</code></strong> without warnings in C11 and C99 mode. For a clean
compilation with <strong><code>gcc -std=c90</code></strong>, add <strong><code>-Wno-format</code></strong> to
<strong><code>CSILENCE</code></strong> in <strong><code>Makefile</code></strong>.</p>
<hr />
<TABLE><TR>
<TD><a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="/png/by-sa-3.0-88x31.png" /></a></TD>
<TD><P>&copy; Copyright 1984-2019,
<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="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
<TD>&nbsp;<!--<a href="https://validator.w3.org/check?uri=referer"><img src="https://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
</TR></TABLE>
</body>
</html>
-84
View File
@@ -1,84 +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.2.0">
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8"> <link rel="stylesheet"
type="text/css"
href="../hint.css">
<title>Best small program</title>
</head>
<body>
<h1>Best small program</h1>
<p>Volker Diels-Grabsch<br>
<a href="https://njh.eu">https://njh.eu</a></p>
<h2>Judges' comments:</h2>
<h3>To use:</h3>
<pre><code>make
./prog &lt; file &gt; file.Z
</code></pre>
<h3>Try:</h3>
<pre><code>dd bs=1024 count=2048 &lt; /dev/zero | compress &gt; ref.Z
dd bs=1024 count=2048 &lt; /dev/zero | ./prog &gt; dg1.Z
cmp ref.Z dg1.Z
compress &lt; ../mills/Shakespeare.txt &gt; ref.Z
./prog &lt; ../mills/Shakespeare.txt &gt; dg1.Z
cmp ref.Z dg1.Z # Oops, the files differ
zcat &lt; dg1.Z | cmp - ../mills/Shakespeare.txt # Decompresses correctly. What is going on?
</code></pre>
<h3>Selected Judges Remarks:</h3>
<p>Finally, IOCCC now has its own text compression program, and it is short
enough to qualify for the Best Short Program award! That said, can you
compress it down to a one-liner, still producing files in the UNIX compress format,
albeit sacrificing the compression ratio?</p>
<p>Can you explain why the zero file compresses identically by the entry and the
standard compress tool, but the text file compresses differently? The judges know. :)</p>
<h2>Author&rsquo;s comments:</h2>
<h3>A tiny &ldquo;compress&rdquo; tool</h3>
<p><code>Usage:</code></p>
<pre><code>./prog &lt; guidelines.txt &gt; guidelines.txt.Z
</code></pre>
<p><code>Check for correctness:</code></p>
<pre><code>zcat guidelines.txt.Z &gt; guidelines2.txt
diff -s guidelines.txt guidelines2.txt
</code></pre>
<p><code>Of course you can</code><br>
<code>also use 2015/mills2 instead of zcat to verify the output</code><br>
<code>file. The achieved compression ratio roughly matches that</code><br>
<code>of the classic Unix compress tool. And the source code is</code><br>
<code>very compressed, too: It has exactly the same size as the</code><br>
<code>paragraph you are reading right now. And exactly the same</code><br>
<code>shape. Nevertheless, it is portable C99 code that runs on</code><br>
<code>32-bit and 64-bit platforms. It compiles without warnings</code><br>
<code>on both GCC and Clang even with -Wextra and -Weverything.</code></p>
<hr />
<TABLE><TR>
<TD><a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="/png/by-sa-3.0-88x31.png" /></a></TD>
<TD><P>&copy; Copyright 1984-2019,
<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="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
<TD>&nbsp;<!--<a href="https://validator.w3.org/check?uri=referer"><img src="https://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
</TR></TABLE>
</body>
</html>
-210
View File
@@ -1,210 +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.2.0">
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8"> <link rel="stylesheet"
type="text/css"
href="../hint.css">
<title>Most self-aware</title>
</head>
<body>
<h1>Most self-aware</h1>
<p>Volker Diels-Grabsch<br>
<a href="https://njh.eu">https://njh.eu</a></p>
<h2>Judges' comments:</h2>
<h3>To use:</h3>
<pre><code>make
</code></pre>
<h3>Try:</h3>
<pre><code>./prog
sha512sum prog.c || shasum -a 512 prog.c
</code></pre>
<h3>Selected Judges Remarks:</h3>
<p>Before running this one, stay calm. Chill out, have a cup of tea. Is this bad?</p>
<p>To understand what is going on here, please check if you are dreaming, or are you dreaming
that you are dreaming? Or is it, wake up from the simulation?</p>
<h2>Author&rsquo;s comments:</h2>
<h3>Almost a hash collision</h3>
<p>This program prints its own SHA-512 hash. To verify, run:</p>
<pre><code>sha512sum prog.c; ./prog
</code></pre>
<p>Output:</p>
<pre><code>43bd0c4381a5078d2850fca9ae5e0647596bcc03cd67d8d973ad02ff35c316c728e7b347ca70abe6c74e745e63646cc7643cb0cffcd3d9a969cbf31a7ce5bf68 prog.c
43bd0c4381a5078d2850fca9ae5e0647596bcc03cd67d8d973ad02ff35c316c728e7b347ca70abe6c74e745e63646cc7643cb0cffcd3d9a969cbf31a7ce5bf68
</code></pre>
<p>It started as a complicated &ldquo;hello world&rdquo; program that prints some
random hex digits instead of &ldquo;hello world&rdquo;. Then, the digits were
adjusted until the resulting program matched its own SHA-512 hash,
via brute force through all 2<sup>512</sup> possibilities. Just kidding.</p>
<p>This wasn&rsquo;t brute force, but involved quite some math, using a variant
of Jane Doe&rsquo;s algorithm for generating SHA-512 collisions efficiently.
If you still don&rsquo;t believe me, you are right.</p>
<p>No crypto was broken in the making of this program!</p>
<p>The trick is that under the hood, this program is a quine! That is,
it is aware of its own source code in string representation. But
instead of printing that string, its SHA-512 hash is computed and
printed. So two major steps were needed to obfuscate this program:</p>
<ul>
<li>Step 1: Hide the quine</li>
<li>Step 2: Hide the SHA-512 computation</li>
</ul>
<p>Note that both steps were achieved mostly algorithmically. The code
is otherwise as short and as clean as possible. The implementation is
portable C99 code for 32-bit and 64-bit systems that compiles without
any warnings on current GCC and Clang versions even with -Wextra and
-Weverything. The program is composed of mostly pure functions, and
the &ldquo;#define"s are only used to shorten redundant parts of the code,
they are not meant to obfuscate much. Having that out of the way, how
are step 1 and step 2 achieved then?</p>
<p>Regarding step 1, note that the large string literal &ldquo;`x{bh}ndbq&hellip;&rdquo;
in the last line doesn&rsquo;t look like C code. Moreover, it is too short
to contain even a compressed representation of all preceding and
subsequent code. Instead, the preceding code including the &lsquo;&ldquo;&rsquo;
character has already been run through the SHA-512 computation by an
external script. The internal state of the SHA-512 computation at
that point has been extracted and encoded into the string. This works
because the preceding code is exactly 1280 bytes, which is a multiple
of 1024 bits, the block size of SHA-512. The program itself then just
continues the SHA-512 computation from that point, adding the last
1024-bit block, finalizing the hash and printing it. The last block
is taken directly from the string literal at runtime, plus the
subsequent code which consists of just &lsquo;&rdquo;&rsquo;, &lsquo;;&rsquo; and &lsquo;\n&rsquo;. Those 3
characters are short enough to be hidden in &hellip; well, let&rsquo;s leave this
as an exercise for the reader.</p>
<p>To summarize, the main trick here is to move the string constant to
the end, so the preceding code can be precalculated and the subsequent
code is short enough to be hidden anywhere.</p>
<p>Regarding step 2, almost all macros, functions and variables have
meaningless single-letter names. Moreover, the SHA-512 computation is
reduced to the special case of adding just one block and immediately
finalizing it, where the total size is known in advance.</p>
<p>But this is not enough! For SHA-512 we need 8 initial hash values and
80 round constants, which are very characteristic. If any of them
appeared in the source, a quick web search (e.g. for 0x428a2f98d728ae22)
would tell the reader immediately what&rsquo;s going on. Because of the
precomputation, the 8 initial hash values are not needed, but the
80 round constants are.</p>
<p>It is almost impossible to hide those 640 bytes in the source.
Luckily, the round constants where not chosen by fair dice rolls.
They are the fractional parts of certain irrational numbers, namely,
the cube roots of the first 80 primes. So the round constrants are
calculated at runtime, which makes the program shorter and adds
another layer of obfuscation.</p>
<p>While this sounds like just iterating primes and executing pow(), this
turned out to be harder than expected. If we were computing SHA-256,
it would have been as simple as that, because the round constants
would have been 32-bit values. However, SHA-512 needs the cube roots
at 64-bit precision, while double has only 53-bit mantissa precision.</p>
<p>Using higher-precision floating point is no option here, because the
program is meant to be portable C99. And implementing
arbitrary-precision arithmetic would have been overkill and would have
increased the program size dramatically.</p>
<p>Instead, the program just multiplies. That is, it computes cubes
instead of cube roots. It steps through cube root candidates via
bisection, and calculates their cubes until those match the given
prime. Thus, we don&rsquo;t need floating point and can use 64-bit integers
instead. But that still doesn&rsquo;t solve the problem as it poses the
following new challenges:</p>
<ul>
<li>Challenge 1: We can multiply at most two 32-bit numbers at once.</li>
<li>Challenge 2: We need to calculate with at least 67-bit precision.</li>
<li>Challenge 3: We need to truncate the cube root result.</li>
</ul>
<p>The reason for challenge 1 is that in portable C99, the result must
fit into the same data type. To multiply two 64-bit integers we would
need a 128-bit integer for the result. So we can at most multiply two
32-bit integers to get the 64-bit product at full precision. While
GCC and Clang both support 128-bit arithmetics, that isn&rsquo;t standard
and wouldn&rsquo;t have been portable C99.</p>
<p>The reason for challenge 2 is that cube root of the 80th prime is
around 7, so we need to compute with 3 bits for the integral part and
64 bits for the fractional part.</p>
<p>The reason for challenge 3 is that the cube of a 67-bit number is
3*67=201 bits, but fortunately we only need to check if it is close
enough to the actual prime. It won&rsquo;t be exactly e.g. &ldquo;409.0000&hellip;&rdquo;
anyway, but must be accurate enough to distinguish the correct cube
root from its neighbours, e.g. the same number with the 64th
fractional digit increased.</p>
<p>The solution here is to split the 67-bit input into 3 integers of
24-bit each. Those are cubed using the multiplication formulas
numbers with 3 &ldquo;digits&rdquo; of base 2<sup>24</sup> each. During that calculation,
at most two values are multiplied at once, and the accuracy of
intermediate values is reduced using right-shifts as far as allowable
for the computation. Finding woking right-shift values was mostly
trial-and-error, producing correct results for the first 80 primes,
but not much more. Moreover, for some terms it was possible to leave
them out entirely, especially higher-order terms of the last digits.
Luckily, in the end, all intermediate results did fit into 64-bit
integer addition and multiplication, but that was not obvious at the
beginning.</p>
<p>That&rsquo;s it.</p>
<p>Well, I could continue with details about the encoding of the internal
state values into the string, how to avoid escaping issues, how to
find short notations for various loops, how to get rid of if(), where
the final &ldquo;\&rdquo;;\n" is stored, how to eliminate intermediate values and
arrays by reordering of operations, and so on. But those were all
minor issues compared to the challenges described above. What&rsquo;s
documented here is all you need to know to write your own version of
that program.</p>
<p>I&rsquo;d like to finish with an open problem:</p>
<p>Is it possible for the cubing and bisection to be implemented with
just two parts instead of three? That would simplify the formulas a
lot. For example, one could split the 67-value into two 34-bit parts,
but whenever one multiplies two of them, one needs to right-shift one
of them by at least 4 bits, or both by 2. Or, one splits the 67 bits
asymmetrically? I wasn&rsquo;t able to make it work with 2 parts, but that
doesn&rsquo;t have to mean anything.</p>
<hr />
<TABLE><TR>
<TD><a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="/png/by-sa-3.0-88x31.png" /></a></TD>
<TD><P>&copy; Copyright 1984-2019,
<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="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
<TD>&nbsp;<!--<a href="https://validator.w3.org/check?uri=referer"><img src="https://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
</TR></TABLE>
</body>
</html>
-169
View File
@@ -1,169 +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.2.0">
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8"> <link rel="stylesheet"
type="text/css"
href="../hint.css">
<title>Best use of space and time</title>
</head>
<body>
<h1>Best use of space and time</h1>
<p>Gil Dogon</p>
<h2>Judges' comments:</h2>
<h3>To use:</h3>
<pre><code>make
./prog &lt; pattern.mc
</code></pre>
<h3>Try:</h3>
<pre><code>./prog &lt; glider.mc
./prog &lt; infinite_5x5.mc
./prog &lt; mosquito5.mc
# Press the minus key a few times until you see white specks,
# then press space, and the ] key a few times.
./prog &lt; message.mc
</code></pre>
<h3>Selected Judges Remarks:</h3>
<p><a href="http://ioccc.org/years-spoiler.html#1991_davidguy">1991/davidguy</a>,
<a href="http://ioccc.org/years-spoiler.html#2011_blakely">2011/blakely</a>,&hellip;</p>
<p>&hellip;This entry likely concludes the IOCCC category &ldquo;Cellular automata simulators&rdquo;,
it would be very hard to beat it on its field.</p>
<p>FYI: The .mc extension stands for Golly macrocell format.</p>
<p>We truly have not much more to add, except two things:</p>
<ul>
<li><p>If a large sparse pattern is given, at the start of the program
you are much more likely to see a blank board rather than the loaded configuration,
and to see it, you may need to zoom out a few times.</p></li>
<li><p>if you&rsquo;re using a virtual machine with less than 4 Gb of available
model RAM, you&rsquo;d want to reduce the value of the Z define in the Makefile
to 0x10000000, otherwise the entry will promptly crash.</p></li>
</ul>
<p>In the interest of saving lives, this entry was not fuzzed.</p>
<h2>Author&rsquo;s comments:</h2>
<h3>What is it?</h3>
<p>Just run with no arguments on an X11-compatible system using one of the supplied input .mc files as standard input. Press &lsquo;-&rsquo; several time to zoom out if neccessary, then press space. For acceleration press &lsquo;]&rsquo; several times. Thats rather quick dont you think?</p>
<h3>Historical Timeline.</h3>
<ul>
<li>3.5 Billion years ago: Microrganism life appears on earth</li>
<li>3000 BC: Ankh symbol is used in Egyptian hyroglyphs to represent life.</li>
<li>1940s: John Von Neumann and Stanislav Ulam are interested in artificial life eventually kick starting research on Cellular Automata.</li>
<li>1970: J.H. Conways research discovers a rather minimal set of rules that seems quite interesting. Conways game of life gets published in Gardners Scientific American column.</li>
<li>1970&rsquo;s: According to Knuth, a significant portion of computer time in the world is spent simulating GOL, mostly without the awareness of the people footing the bill.</li>
<li>1984: Bill Gosper invents the Hashlife algorithm. His implementation runs on Symbolics Lisp Machines. Unrelated to that, but in a cosmic coincidence the first IOCCC is run!</li>
<li>December 2000: Tom Rokicki has a breakthrough implementing Hashlife in C, efficient, stable and production ready for modern machines.</li>
<li>2006: First version of Golly by Andrew Trevorrow and Tomas Rokicki. Brings the delights of hashlife to the masses.</li>
</ul>
<p>Which brings us to the present moment in time.</p>
<h3>Full documentation and keys UI.</h3>
<p>Yes, this program is Conway&rsquo;s game of life graphic simulator implementing Bill Gosper&rsquo;s hash life algorithm. The entry&rsquo;s UI is rather terse and somewhat obfuscated, as it should be. Also, when you accidentally, or not, press any of the keys not specified bellow, some stuff will happen or not, there is no guarantee whatsoever.</p>
<p>The program should be used as follows:</p>
<p>The standard input should contain a Golly macrocell format file for a two state automaton. See: http://golly.sourceforge.net/Help/formats.html. Of course only Conways GOL rules are supported, so rules in the files are ignored. The supplied input examples should be quite interesting. Except one, all are taken from Golly&rsquo;s standard distribution. Information and credits to their designer are in the header comment of each.</p>
<ul>
<li>For image navigation use the arrow keys, and zoom in and out by the +/- keys (without pressing the shift on the +)</li>
<li>Space : Toggle start/stop.</li>
<li>0(zero): Toggle single step/free run mode.</li>
<li>Backspace: Toggle direction for the arrow of time.</li>
<li>]: Increase speed (time step) by a factor of 2.</li>
<li>[: Decrease speed (time step) by a factor of 2.</li>
</ul>
<p>Notice that when going backward in time we ignore current timestep setting and just jump by the amount that was specified before. However going forward is always using the current time step.</p>
<p>There is a minimal text printout by the program, so you can know what Generation your are in(G:), Internal memory allocated till now (M:), and then which Level is the current macrocell (L) and which zoom Scale you are watching (S).</p>
<h3>Portability issues.</h3>
<p>This entry is quite portable hopefully on most modern platforms. It assumes X Window support of course. More than 2GBytes memory is recommended. Configuration through makefile is provided for the display windows size and for the memory usage. The makefile provided configuration (Z=0x20000000) will need a system with 4GB DRAM to run nicely. There are several other salient assumptions though:</p>
<ul>
<li>The entry assumes sizeof(long)=8. However it actually almost avoids using any pointers which are 64 bits this days, in order to save space. On machines with sizeof(long)=4 try adding #define long long long &hellip;</li>
<li>The entry assumes the X11 displays default visual has 24 bit depth (RGB).</li>
<li>The entry assumes little endianity (in only one place though! if you have powerpc you can try and find that place to make it work), but more than this it assumes unaligned loads of 64 bits longs are supported, i.e. it assumes that a long can be loaded from any address that could hold an int otherwise. On non antiquated X86 you&rsquo;ll be fine.</li>
<li>The entry heavily relies on bit complement arithmetic (you dont say!).</li>
</ul>
<h3>Limitations.</h3>
<p>Foremost the entry is very strict, unsafe and picky regarding its input. Anything straying from the standard Golly macrocell legal format will result in undefined behavior, meaning mostly a very defined core dump. Since aforementioned core is rather large by default (about 4Gb) it is highly recommended to &lsquo;set limit coredumpsize 0&rsquo; in the shell before playing with fire &hellip;</p>
<p>This entry needs quite a lot of memory to be effective, but by modern standards that is not too much. It does not do any garbage collection, so sooner or later memory will run out, resulting, surprise, surprise, in a core dump. On the plus side, this enables the nice time reversal feature&hellip; Anyway the amount of memory used can be controlled by the Makefile -DZ=&hellip; argument. With the default Z, the program will support in total about 240 million 64bit longs for the internal memory, which should be sufficient for about 100 million nodes+leafs, as each node is 3 longs and each leaf is 2.
<em>Important:</em> Makefile Z define must be apower of two!</p>
<p>Zooming out past about S58 scale will enter a buggy twilight zone as only long integers are used in the drawing code. Reverting to doubles could have remedied that, but then I&rsquo;d need to use a lot of ldexps which would take the program over the size limit. Also the program will crash once the universe goes past level 64, though this is simply fixed by modifying a single constant in the program, can you find it ? Anyway 2<sup>58</sup> squared is quite a big enough universe for such a tiny progam to simulate, no ?</p>
<p>In case cell memory did not run out, or your pattern did not grow too big, and you have had patience enough and did not increase speed too much, you can run out of the history buffer after 33333 steps.</p>
<p>If all of the above did not happen and result in the expected core dump, you will encounter the final limitation, which is the absence of an escape key. Just close the window or use ^C to exit &hellip;.</p>
<h3>Warnings.</h3>
<p>Oh don&rsquo;t get me started on the torrent of litanies gcc emits when used with -Wall ! Does it think I have not memorized by heart C&rsquo;s precious operator precedence table (or at least have a cheatsheet nearby) that it dares suggest extra parentheses that would take the program over the limit ? And what if I do not use a variable here or there, do I have to pay extra tax for every orphaned variable?</p>
<p>There is the reasonable warning about some longs printed as ints but its OK too, trust me.</p>
<p>Then there&rsquo;s the warning about &lsquo;gets&rsquo; being unsafe, which is indeed the only one that appears by default in some versions of gcc linker. Yes Virginia, I know it is unsafe, and I would not recommend anyone using this entry as part of a web daemon, or a spaceship, no, Seriously Dont do that!</p>
<h3>Obfuscations.</h3>
<p>Well almost none of the obfuscations are done on purpose, but mostly out of necessity, so all identifiers possible to be one character, are, and they are mercilessly reused. In the main There&rsquo;s even a nice little identifier first used as a global and then reused (shadowed) in the <em>same</em> scope, and this did not produce even a lile squeak of a warning from the compiler! Macro compression is raher sparingly used, however Magic numbers abound everywhere, and bit twiddling is magical too. Do you know for example why we have unsigned F=-1 ? (No warning there of course :) Hint:Later in the program you have F/=17. Did that make any sense? Further hint: print the resulting F in hexadecimal&hellip;</p>
<p>And yes, the layout hint involves a mix of the most trendy typographical character juxtaposed against a very ancient one, Not to mention the program includes some famous name dropping and documents itself as usual.</p>
<h3>Further spoilers, engineering, and obfuscation galore.</h3>
<p>Those wait for you, curious and interpid reader, in the attached apohlife.c file, Which is a partially obfuscated version of the program I wrote with a lot of helpful annotations and comments for myself and posterity, revealing some of the magic under the hood. This program is also a somewhat improved version which uses ldexps in the draw routine and has bigger constants, so it can zoom up to level 1024 if memory allows, and it tries its best to avoid dumping core on the poor user when its memory runs out, rather it enters freeze mode where you can still travel in calculated frozen space-time. Well, its no nice and tame, it even has an escape key, usage message, and to top it all it even avoids gets!</p>
<h3>Special thanks.</h3>
<p>To Tom Rockiki, the original co-writer of Golly, a personal friend and hashlife master, who reviewed some earlier versions of the entry and freely shared some of his vast knowledge regarding GOL programming and hashlife. As a free bonus, Tom has allowed me to show his code which is probably the most efficient yet most obfuscated way of calculating the GOL function on a 64 bits 8*8 leaf:</p>
<p><code>c
unsigned long life8x8(long a) { unsigned long aw = a &lt;&lt; 1, ae = a &gt;&gt; 1, s0 = aw ^ ae, s1 = aw &amp; ae, hs0 = s0 ^ a, hs1 = (s0 &amp; a) | s1, hs0w8 = hs0 &gt;&gt; 8, hs0e8 = hs0 &lt;&lt; 8, hs1w8 = hs1 &gt;&gt; 8, hs1e8 = hs1 &lt;&lt; 8, ts0 = hs0w8 ^ hs0e8, ts1 = (hs0w8 &amp; hs0e8) | (ts0 &amp; s0); return (hs1w8 ^ hs1e8 ^ ts1 ^ s1) &amp; ((hs1w8 | hs1e8) ^ (ts1 | s1)) &amp; ((ts0 ^ s0) | a); }
</code>
This uses only 19 bitwise operations and six shifts to calculate the inner 6x6 next generation bits of the input 8x8 !</p>
<hr />
<TABLE><TR>
<TD><a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="/png/by-sa-3.0-88x31.png" /></a></TD>
<TD><P>&copy; Copyright 1984-2019,
<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="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
<TD>&nbsp;<!--<a href="https://validator.w3.org/check?uri=referer"><img src="https://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
</TR></TABLE>
</body>
</html>
-196
View File
@@ -1,196 +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.2.0">
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8"> <link rel="stylesheet"
type="text/css"
href="../hint.css">
<title>Best collaborative graphics</title>
</head>
<body>
<h1>Best collaborative graphics</h1>
<p>Etienne Duble<br>
<a href="https://lig-membres.imag.fr/duble">https://lig-membres.imag.fr/duble</a><br>
Twitter: @etienne_duble</p>
<h2>Judges' comments:</h2>
<h3>To use:</h3>
<pre><code>make
</code></pre>
<h3>Try:</h3>
<pre><code>./prog /tmp/drawing
(open another window / terminal)
./prog /tmp/drawing
(open more terminals....)
./prog /tmp/drawing
</code></pre>
<h3>Selected Judges Remarks:</h3>
<p>After starting the program, use the cursor keys, then try some modes, like &ldquo;p&rdquo;
or &ldquo;l&rdquo; (they toggle).</p>
<h2>Author&rsquo;s comments:</h2>
<h3>Introduction</h3>
<p>This program is a <strong>graphics editor</strong>, running on the terminal.</p>
<p>It provides <strong>collaborative</strong> features: one can join the drawing session
of someone else by just opening the same file!</p>
<h3>Getting started</h3>
<p>The program can run on Linux, FreeBSD, Mac OS X, and in most terminals.
See section &lsquo;Limits, Portability&rsquo; for more info.</p>
<p>To build, type <code>make</code> (assuming gcc) or <code>make CC=clang</code>.</p>
<p>Then you can start the program. It expects a file path as its first argument:</p>
<pre><code>$ ./prog /tmp/drawing
</code></pre>
<p>(If not started this way, <code>prog</code> will refuse to start.)</p>
<p>If the file does not exist, you will start with a blank drawing.</p>
<p>If someone else (or another <em>instance of yourself</em>, maybe??) is already
editing this file, you will join the session!</p>
<h3>Edition features</h3>
<ul>
<li><strong>arrow keys</strong>: move cursor.</li>
<li><strong>p</strong> key: enter <em>pen</em> mode (type <strong>p</strong> again to return to the default <em>move</em> mode).</li>
<li><strong>l</strong> key: enter <em>line</em> mode (type <strong>l</strong> again to validate the line and return to the <em>move</em> mode).</li>
<li><strong>c</strong> key: cycle through a small set of different <em>colors</em>.</li>
<li><strong>q</strong> key: quit the editor. The drawing is automatically saved.</li>
</ul>
<p>The mode and current color is indicated at the bottom left corner of
the editor.</p>
<h3>Bonus features</h3>
<ul>
<li>If you just want to display the content of a drawing file, you do not
need to start the editor. Just <strong>execute the drawing file</strong>: <code>./&lt;the-file&gt;</code>.
(This will fail if someone is still editing the file, though.)</li>
<li><code>ls --color &lt;drawing-files...&gt;</code> will probably select different colors
to indicate whether a drawing file is being edited or not. :-)</li>
</ul>
<h3>Obfuscation</h3>
<p>You will probably have a hard time analyzing this entry, because:</p>
<ul>
<li>Analyzing a system made of several communicating programs is known to
be a complex task. (And if you think that observing a single-user drawing
session will be a good starting point, read on.)</li>
<li>Code coverage of single vs multi-user sessions is more or less the same. :-)</li>
<li>Code coverage when using <em>move</em>, <em>pen</em> or <em>line</em> modes is almost the same.
(so, is there a Bresenham algorithm somewhere??)</li>
<li>Some OS resource values and stdlib call results are inferred.</li>
<li>Whenever possible, variable names are reused.</li>
<li>You might start analyzing escape code sequences right now, but warming up
your brain is actually recommended. Start with a simple question such as:
<em>in inverse video mode, will a space char show the foreground color or
background color?</em></li>
</ul>
<h3>A few more things</h3>
<p>Did you notice the <code>enum</code> declaration? Could it be just an <code>int</code> or <code>const int</code>
variable, instead? (spoiler: http://c-faq.com/ansi/constasconst.html)</p>
<p>If your keyboard has no arrow keys, you can probably find alternate keys by
reading the source code.</p>
<h3>Limits, Portability</h3>
<p>I tested the program on several Linux systems, on FreeBSD 12, and on
Mac OS X (mojave).</p>
<p>On Linux, the program uses an OS-specific detail to hide communication
artefacts, and avoids the need to remove them on exit.
Since this is Linux-specific, it was not possible on FreeBSD or Mac OS.
Its behavior is a little more <em>dirty</em> there.</p>
<p>The program should work on most terminals that support 8-bit colors,
inverse video mode, and movement escape codes, e.g. <code>xterm</code>, <code>gnome-terminal</code>,
<code>terminator</code>, etc.</p>
<p>Note: the drawing files <code>prog</code> generates are probably even more portable than
<code>prog</code> itself!</p>
<h3>Drawing area size</h3>
<p><em>The drawing area size is set at compilation time</em>.</p>
<p>The default size is the one of my xterm (see top of Makefile).
You may set it to the full size of your terminal window by typing:</p>
<pre><code>$ make fullscreen
</code></pre>
<p>IMPORTANT NOTES:</p>
<ul>
<li><strong>The program compiled with a given size will fail to reload a drawing file
with a different size!</strong></li>
<li>No scrolling is implemented (sorry but that would be too much for rule2!),
so any peer reaching the session should have a terminal with the same
size or larger.</li>
</ul>
<h3>prog.c vs prog.orig.c</h3>
<p>The file <code>prog.orig.c</code> is the one I submitted.</p>
<p>Judges proposed a small update: the program was using macro <code>FD_SET</code> inside an
expression, which breaks compilation on Mac OS X. Wrapping this macro into a
function was enough to fix this compilation issue.</p>
<p>However, that was not enough to make the program work on Mac OS X. If you analyse
the program you will see that it heavily relies on OS resources. And, for this
first version of the program, you even needed to increase default <code>sysctl</code>
parameters to make it work on FreeBSD (this was the purpose of file <code>check-os.sh</code>).
I tried hard to tune Mac OS X the same, but failed.</p>
<p>The simple fact Judges proposed this update meant they wish it could work on Mac.
And if judges wish something, it <strong>has to</strong> be done. ;)
So I refactored a little more the program to reduce OS resources consumption.
Or maybe not reduce consumption, but consume them differently&hellip;
And I obtained <code>prog.c</code>. With this version, no need to touch <code>sysctl</code> parameters,
and it works on Mac OS X too!
I must confess it was challenging to remain below the size limit with this little
change.</p>
<hr />
<TABLE><TR>
<TD><a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="/png/by-sa-3.0-88x31.png" /></a></TD>
<TD><P>&copy; Copyright 1984-2019,
<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="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
<TD>&nbsp;<!--<a href="https://validator.w3.org/check?uri=referer"><img src="https://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
</TR></TABLE>
</body>
</html>
-124
View File
@@ -1,124 +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.2.0">
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8"> <link rel="stylesheet"
type="text/css"
href="../hint.css">
<title>Most in need of debugging</title>
</head>
<body>
<h1>Most in need of debugging</h1>
<p>Yusuke Endoh<br>
Twitter: @mametter</p>
<h2>Judges' comments:</h2>
<h3>To use:</h3>
<pre><code>make
</code></pre>
<h3>Try:</h3>
<pre><code>./prog
gdb ./prog || llvm ./prog
</code></pre>
<h3>Selected Judges Remarks:</h3>
<p>The purpose of this program is to crash. You&rsquo;ll want to have memorized &ldquo;man
ascii&rdquo; when debugging it to reveal its purpose.</p>
<h2>Author&rsquo;s comments:</h2>
<h3>backtrace quine</h3>
<p>Compile prog.c with no optimization.</p>
<pre><code>$ gcc -g -O0 -o prog prog.c
</code></pre>
<p>Then, run it. You will see a segmentation fault.</p>
<pre><code>$ ./prog
Segmentation fault (core dumped)
</code></pre>
<p>Let&rsquo;s debug. As usual, run it under gdb.</p>
<pre><code>$ gdb ./prog
(gdb) run
Starting program: /home/.../prog
Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
</code></pre>
<p>Okay, check the backtrace.</p>
<pre><code>(gdb) backtrace
#0 0x0000000000000000 in ?? ()
#1 0x0000555555555201 in x23 () at prog.c:35
#2 0x000055555555571a in x64 () at prog.c:100
#3 0x0000555555555747 in x65 () at prog.c:101
#4 0x0000555555555774 in x66 () at prog.c:102
#5 0x00005555555557ce in x69 () at prog.c:105
#6 0x0000555555555828 in x6e () at prog.c:110
#7 0x0000555555555747 in x65 () at prog.c:101
...
</code></pre>
<p>See the line numbers and lookup the ASCII table.</p>
<pre><code> 35 = '#'
100 = 'd'
101 = 'e'
102 = 'f'
105 = 'i'
110 = 'n'
101 = 'e'
...
</code></pre>
<h4>One more thing</h4>
<p>The original program can be used as a GDB command file.</p>
<pre><code>$ gdb -q -x prog.c ./prog | cat
Reading symbols from ./prog...done.
Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
#0 0x0000000000000000 in ?? ()
#1 0x0000555555555201 in x23 () at prog.c:35
#2 0x000055555555571a in x64 () at prog.c:100
#3 0x0000555555555747 in x65 () at prog.c:101
#4 0x0000555555555774 in x66 () at prog.c:102
#5 0x00005555555557ce in x69 () at prog.c:105
#6 0x0000555555555828 in x6e () at prog.c:110
#7 0x0000555555555747 in x65 () at prog.c:101
...
</code></pre>
<p>By using this, you can confirm that it is actually a quine.</p>
<pre><code>$ gdb -q -x prog.c ./prog | sed -n -r 's/#.*:([0-9]+)/\1/p' | awk '{printf "%c",$1}' &gt; prog2.c
$ diff prog.c prog2.c
</code></pre>
<hr />
<TABLE><TR>
<TD><a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="/png/by-sa-3.0-88x31.png" /></a></TD>
<TD><P>&copy; Copyright 1984-2019,
<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="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
<TD>&nbsp;<!--<a href="https://validator.w3.org/check?uri=referer"><img src="https://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
</TR></TABLE>
</body>
</html>
-192
View File
@@ -1,192 +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.2.0">
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8"> <link rel="stylesheet"
type="text/css"
href="../hint.css">
<title>Most in need of wide space</title>
</head>
<body>
<h1>Most in need of wide space</h1>
<p>Edward Giles</p>
<h2>Judges' comments:</h2>
<h3>To use:</h3>
<pre><code>make prog
./prog infile.wav outfile.wav
</code></pre>
<h3>Try:</h3>
<pre><code>play MonodyVocals.wav
./prog MonodyVocals.wav
play out.wav
</code></pre>
<h3>Selected Judges Remarks:</h3>
<p>Do you need to pretend enjoying a more spacious living environment than you actually are in,
or the great outdoors with mountains and canyons, when recording your outgoing voicemail message?
Then don&rsquo;t waste another minute! Record yourself, send the audio file through this entry,
and let your callers be surprised.</p>
<h2>Author&rsquo;s comments:</h2>
<h2>Description</h2>
<p>This program takes a WAV audio file as input, and applies an artificial reverberation effect to it. It works by feeding the audio through a number of delay lines of various lengths, with various amounts of feedback, to create a smooth echo that fades away over time. A number of parameters of the effect can be altered, to change its sonic characteristics.</p>
<p>BlockDiagram.png is a block-diagram of the internal structure of the reverb algorithm, which is most likely easier to understand than the source code.</p>
<p>MonodyVocals.wav is for testing the program: It is an extract of the unprocessed vocals from <a href="https://www.youtube.com/watch?v=B7xai5u_tnk">Monody by TheFatRat, featuring Laura Brehm</a>. The track was published under a free license.</p>
<p>This program has also been successfully compiled on Windows, with both the <a href="https://bellard.org/tcc/">Tiny C Compiler</a> and Microsoft&rsquo;s C/C++ compiler. However, the latter reports warnings about loss of information when converting floats, and that <code>void (*)()</code> and <code>void (*)(void)</code> are not the same thing.</p>
<p>Interesting fact: The size of the program from <code>./iocccsize -i</code> is 2019.</p>
<p><strong>How to use</strong>:</p>
<pre><code>./prog input [output [size [dry [wet [damping]]]]]
prog.exe input [output [size [dry [wet [damping]]]]]
</code></pre>
<ul>
<li><code>input</code>: The path to the input file. Required.</li>
<li><code>output</code>: The path to the output file. Optional, defaults to <code>out.wav</code>.</li>
<li><code>size</code>: The perceived size of the room, i.e. the approximate amount of time taken for the echo to fade away. Optional, default 1.6 seconds.</li>
<li><code>dry</code>: The amount of unprocessed signal (&ldquo;dry&rdquo; in audio terminology) to add to the output. Optional, default 0.3 or 30%.</li>
<li><code>wet</code>: The amount of processed (&ldquo;wet&rdquo;) signal to add to the output. Optional, default 0.5 or 50%.</li>
<li><code>damping</code>: The amount by which high frequencies are damped out as the echo continues. This models the tendency for higher frequencies to be absorbed more than lower ones. Increasing this value causes the echo to be less &ldquo;harsh&rdquo; and more &ldquo;muffled&rdquo;. Optional, default 0.06 or 6%.</li>
</ul>
<p>The values <code>size</code>, <code>dry</code>, <code>wet</code>, and <code>damping</code> can be specified either as decimal numbers (e.g. 0.35) or as percentages (e.g. 35%).</p>
<p>The default settings are designed to make the effect obvious rather than subtle, so it may be a good idea to adjust the ratio of &ldquo;dry&rdquo; to &ldquo;wet&rdquo;, to give a more pleasant result:</p>
<pre><code>./prog in.wav out.wav 1.8 80% 15%
</code></pre>
<p>The program only supports WAV files, and only mostly. Other audio formats, such as MP3, are not supported because they are difficult to decode, but there are free programs such as <code>ffmpeg</code> that can perform the conversion. Some of the advanced features of the WAV file format are also not supported, such as metadata, 3 or more channels, or a bit depth other than 16 bits. Fortunately, WAV files that don&rsquo;t use these features are very common. The program validates the input file, so passing it a file it can&rsquo;t process will cause the program to print <code>Bad input file</code> or <code>Wave file must be 16 bits,1-2 channels.</code> depending on what it thinks the problem is. If the output file cannot be opened, the program will print <code>Can't open output file</code>.</p>
<h2>Assumptions</h2>
<ol>
<li>The code is compiled using the C99 or C11 standard</li>
<li>Values are stored in memory in little-endian order</li>
<li><code>float</code> is a floating-point type of any size, such that all zero bits represents the number zero</li>
<li><code>int16_t</code> and <code>int32_t</code> are 2&rsquo;s-complement, <code>sizeof(int16_t) == 2</code> and <code>sizeof(int32_t) == 4</code>.</li>
</ol>
<h2>Obfuscations</h2>
<p>The main obfuscation is that digital signal processing algorithms are inherently opaque. They just consist of iterating through a list of floating-point numbers and performing a series of arithmetic operations on each value. Even if this entry were entirely cleaned of all other obfuscation, it will appear to the average programmer to do the following:</p>
<ul>
<li>Read and validate command-line arguments.</li>
<li>Read and validate the header portion of the input file, and print some errors if that fails.</li>
<li>Write a modified form of that header into the output file.</li>
<li>Print the parameters read from the command-line arguments, in a human-readable format.</li>
<li>Dynamically allocate some arrays of floating-point numbers, to be used later, with lengths based on the <code>size</code> parameter</li>
<li>Read 16-bit audio samples from the input file, converting them to floating-point.</li>
<li>For each audio sample, do a weird combination of addition, subtraction, and multiplication by constants, using the previously-allocated arrays to store results between iterations. Write the resulting audio samples to the output file, converting them back to 16-bit integers.</li>
<li>Close all of the file handles and free the memory.</li>
</ul>
<p>Note that no part of the above description of the code&rsquo;s function had anything to do with echoes in a room. The purpose of the code is therefore hidden.</p>
<p>The source code, on cursory inspection, appears to be a jumbled series of characters arranged into three arcs, representing sound waves. The overall layout distracts people from the fact that it is source code rather than only ASCII art, and the random appearance of the code discourages people from trying to decipher it.</p>
<p><code>#define</code>s are used to abbreviate the code, which has a side effect of making it very slightly harder to read.</p>
<ul>
<li><code>k</code> is just a general-purpose replacement for 16.</li>
<li><code>i</code> is the number of delay-lines to allocate and use (currently 24).</li>
<li><code>q</code> is an abbreviation for multiplying two elements of <code>w[]</code> together.</li>
<li><code>u()</code> is used to display percentages with proper rounding.</li>
<li><code>j()</code> imposes an upper limit on a floating-point value, and then negates it. This operation is used eight times.</li>
<li><code>D()</code> abbreviates a call to <code>setvbuf</code>, used to speed up file I/O.</li>
<li><code>l()</code> is used to clip audio samples to the acceptable range, and convert them to 16-bit integers for output.</li>
<li><code>g()</code> handles errors.</li>
<li><code>C()</code> contains the bulk of the signal-processing code, as well as a preprocessor obfuscation trick: If you were to read the body of the macro out of context, it will appear to have multiple mismatched square brackets, since <code>[</code> occurs more than <code>]</code>. However, this macro is always invoked with arguments such as <code>C(v],+10)</code> which contain an unmatched <code>]</code> character. When the macro is used in this manner, the extra <code>[</code>s in the macro&rsquo;s body are matched with the <code>]</code>s added through the first argument.</li>
</ul>
<p>Every variable name is one letter long. This allows the code to fit into the IOCCC size limit, and it also makes the purpose of a given variable much less clear. For example, it is not evident from the name of the variable <code>t</code> that it contains pointers to the delay-line arrays.</p>
<p>As many values as possible have been crammed into arrays. <code>float w[]</code> contains:</p>
<ul>
<li>the input parameters (<code>w[0]</code> to <code>w[3]</code>)</li>
<li>various constants needed for the reverb algorithm (<code>w[4]</code> to <code>w[9]</code>)</li>
<li>temporary storage of floating-point audio samples (<code>w[10]</code> to <code>w[20]</code>)</li>
</ul>
<p><code>int32_t f[]</code> is even more multi-purpose. It contains:</p>
<ul>
<li>the header of the input file (<code>f[0]</code> to <code>f[11]</code>)</li>
<li>the number of channels in the input file (<code>f[12]</code>)</li>
<li>the number of samples of output to generate (<code>f[13]</code>)</li>
<li>an end-of-file flag (<code>f[14]</code>)</li>
<li>a variable that I forgot the exact purpose of (<code>f[15]</code>)</li>
<li>indices into the circular buffers where audio samples should be inserted (<code>f[16]</code> to <code>f[39]</code>)</li>
<li>indices where audio samples should be read out (<code>f[40]</code> to <code>f[63]</code>)</li>
<li>lengths of the buffers (<code>f[64]</code> to <code>f[87]</code>)</li>
</ul>
<p>All of the strings are concatenated together and &ldquo;encrypted&rdquo; by breaking the string into 4-byte chunks (by casting it to an <code>int32_t*</code>), and then XORing the sequence of ints with a known numeric sequence. The &ldquo;decryption&rdquo; is not done in-place, to avoid writing over the string constant.</p>
<p><code>int32_t *c</code> is a pointer that points into <code>f[]</code>, except that it is often incremented or decremented when it is accessed. In order to determine which indices of <code>f[]</code> are being accessed through <code>c</code> at any given point in the code, you would have to locate the places where <code>c</code> is modified.</p>
<p>In order for this program to read and write WAV files, it needs to parse the header. The necessary information, such as the sample rate and channel count, is defined by the standard to be in somewhat arbitrary locations within the file. Therefore, even if you know which indices of <code>f[]</code> are being accessed, it takes extra effort to look up the WAV file format and determine which field that corresponds to.</p>
<p>Some array accesses (which make up most of the program) have been replaced with harder-to-interpret equivalents, for example:</p>
<ul>
<li><code>X[1]</code> -> <code>1[X]</code></li>
<li><code>f[14]</code> -> <code>10[f+4]</code></li>
<li><code>X[0]</code> -> <code>*X</code></li>
</ul>
<p>Assignments return the assigned value, allowing them to be included into later expressions: <code>10[f]=f[13]&lt;&lt;2; f[1]=20+10[f]+k;</code> is replaced with <code>f[1]=20+(10[f]=f[13]&lt;&lt;2)+k;</code></p>
<p>This technique is used in conjuction with the comma operator to further obscure where the data ends up. For example,</p>
<ul>
<li><code>12[f]=4[++c]&gt;&gt;k;</code> was incorporated into <code>w[0]*=6[f];</code> to yield <code>w[0]*=(12[f]=4[++c]&gt;&gt;k,6[f]);</code></li>
<li><code>w[15]=w[k]=e[12[f]]; w[11]=w[10]=e[1];</code> becomes <code>w[11]=(w[15]=w[k]=e[12[f]],w[10]=e[1]);</code></li>
</ul>
<p>A few other miscellaneous obfuscations have also been done:</p>
<ul>
<li><code>while(++f[15]&lt;12);</code> is used instead of <code>f[15]=12;</code></li>
<li><code>for(s=14[f]=0;s&lt;f[13];s++)</code> is used instead of <code>f[14]=0; for(s=0;s&lt;f[13];s++)</code></li>
<li>The line that contains <code>printf("Hello, world!");</code> is mostly commented out.</li>
</ul>
<hr />
<TABLE><TR>
<TD><a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="/png/by-sa-3.0-88x31.png" /></a></TD>
<TD><P>&copy; Copyright 1984-2019,
<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="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
<TD>&nbsp;<!--<a href="https://validator.w3.org/check?uri=referer"><img src="https://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
</TR></TABLE>
</body>
</html>
-105
View File
@@ -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.2.0">
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8"> <link rel="stylesheet"
type="text/css"
href="../hint.css">
<title>Most in need of whitespace</title>
</head>
<body>
<h1>Most in need of whitespace</h1>
<p>Joshua Karns<br>
Twitter: @jkarnss</p>
<h2>Judges' comments:</h2>
<h3>To use:</h3>
<pre><code>make
./prog &lt; textfile_that_fits_on_the_screen
</code></pre>
<h3>Try:</h3>
<pre><code>make test
./prog &lt; hint.text
</code></pre>
<h3>Selected Judges Remarks:</h3>
<p>If you typically get lost in mazes, watching this program run might &ndash; or might not, YMMV &ndash;
teach you how to find your way in a maze. The algorithm is well-known but the drawing is amazing!</p>
<p>Before running, make sure that your terminal can accommodate the whole file. Before running &ldquo;make test&rdquo;,
make it about 120x40 to be safe, ensuring that you see the @ sign as well as the exclamation mark.</p>
<p>&hellip;Oh, and the first M in YMMV stands for &ldquo;mazing&rdquo;.</p>
<p>A puzzle for the reader: Can you change the program to consider a diagonal movement as one step?</p>
<h2>Author&rsquo;s comments:</h2>
<h2>The Program</h2>
<p>This program is pretty simple! It performs a breadth first search on the
specified graph. The graph can be any ascii text file that has an &lsquo;at&rsquo;
character, which is going to be the starting location, and a &lsquo;!&rsquo; character
which will be the destination.</p>
<p>The nodes on this graph that are spaces are connected with any directly
adjacent nodes that are also spaces. Nodes that aren&rsquo;t spaces are not
connected with anything.</p>
<h2>Compiling and Running</h2>
<p>This program usually compiles under both GCC and clang. Build with:</p>
<pre><code>$(CC) -std=c99 -o tbfs prog.c
</code></pre>
<p>where $(CC) is cc, gcc, clang, or somet other c compiler.</p>
<p>You can then run it with:
cat <input file> | ./tbfs</p>
<p>Examples:
./tbfs &lt; maze
./tbfs &lt; prog.c</p>
<h2>Issues</h2>
<ul>
<li>The program must be ran in a terminal that supports ANSI escape codes for
moving the cursor and changing colors.</li>
<li>Segfaults happen sometimes.</li>
<li>I don&rsquo;t know what memergy management there is, if any.</li>
<li>Ths program will not compile by an ANSI C compiler: it uses for loops, and
it uses C++ style comments. It should compile cleanly using a C99 standard.</li>
<li>Breadth first search is slow (and very slow on certain maps), but my A star
version of this program is too big.</li>
<li>Lots of extra whitespace may be needed if you want to feed in an arbitrary
file.</li>
<li>It fails to compile on GCC sometimes (according to a friend of mine, I&rsquo;ve
not encountered this myself).</li>
<li>The program could be obfuscated much further.</li>
<li>The program contains some unused code and data.</li>
</ul>
<hr />
<TABLE><TR>
<TD><a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="/png/by-sa-3.0-88x31.png" /></a></TD>
<TD><P>&copy; Copyright 1984-2019,
<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="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
<TD>&nbsp;<!--<a href="https://validator.w3.org/check?uri=referer"><img src="https://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
</TR></TABLE>
</body>
</html>
-298
View File
@@ -1,298 +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.2.0">
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8"> <link rel="stylesheet"
type="text/css"
href="../hint.css">
<title>Most functional compiler</title>
</head>
<body>
<h1>Most functional compiler</h1>
<p>Ben Lynn<br>
<a href="https://crypto.stanford.edu/~blynn/">https://crypto.stanford.edu/~blynn/</a><br>
Twitter: @bmxlynn</p>
<h2>Judges' comments:</h2>
<h3>To use:</h3>
<pre><code>make
</code></pre>
<h3>Try:</h3>
<pre><code>(./prog &lt; fib.hs; cat prog.c) &gt; fib.c
cc fib.c -o fib
./fib
</code></pre>
<h3>Selected Judges Remarks:</h3>
<p>A fully functional compiler. The example prints out the 30th Fibonacci number.</p>
<h2>Author&rsquo;s comments:</h2>
<h1>Remarks</h1>
<p>A Haskell compiler. Supports a subset of Haskell more than large enough to
self-host. Like GHC with custom language extensions:</p>
<ul>
<li><p><code>WeDontServeYourType</code>: Compilation failing because of inscrutable type
checking rules? Confused by the ever-growing mire of extensions to the type
system? The solution is simple: no type checking. It also means no
typeclasses. Just pass dictionaries explicitly.</p></li>
<li><p><code>ZeroPauseGarbageCollection</code>: Instead of disruptive stop-the-world garbage
collection, we only tidy up when the world stops of its own accord, that is,
on program termination.</p></li>
<li><p><code>OneHundredPercentPure</code>: Gone is the catch-all lawless IO monad. And no
trace of those scary <code>unsafeThisAndThat</code> functions. All functions must be pure.</p></li>
<li><p><code>SyntaxForTheMasses</code>: See below.</p></li>
</ul>
<h2>Demos</h2>
<p>Build the compiler:</p>
<pre><code>$ $(CC) -o prog prog.c
</code></pre>
<h3>Fibonacci numbers</h3>
<p>Test the compiler on <code>fib.hs</code>:</p>
<pre><code>$ (./prog &lt; fib.hs ; cat prog.c) &gt; fib.c
</code></pre>
<p>Compiling the output produces a binary that prints the 30th Fibonacci number.</p>
<p>The file <code>ghcfib.hs</code> includes <code>fib.hs</code> with some glue code, and shows GHC
also accepts our subset of Haskell:</p>
<pre><code>$ ghc ghcfib.hs
</code></pre>
<h3>Self-hosting compiler</h3>
<p>To avoid spoiling this entry by revealing the original Haskell source, we
instead provide <code>hint.hs</code>, the output of a certain stage of the compiler when
run on itself. This intermediate output is hopefully difficult to understand,
yet is accepted by our compiler:</p>
<pre><code>$ (./prog &lt; hint.hs ; cat prog.c) &gt; hint.c
</code></pre>
<p>The output program behaves like the compiler itself.</p>
<p>Unlike the original source from which it is derived, GHC fails to compile
<code>hint.hs</code>. This is because values have been replaced with their Scott encodings
by this stage, which messes up type-checks; we&rsquo;d need equirecursive types for
it to work.</p>
<h3>Regexes</h3>
<p>The file <code>lol.hs</code> contains an adaptation of <a href="https://www.cs.dartmouth.edu/~doug/nfa.pdf">Doug McIlroy&rsquo;s elegant code from
&ldquo;Enumerating the strings of regular
languages&rdquo;</a>. We exercise it by
showing the first entries of the length-ordered list of all strings consisting
of the characters a and b that contain an even number of a&rsquo;s.</p>
<pre><code>$ (./prog &lt; lol.hs ; cat prog.c) &gt; lol.c
</code></pre>
<p>A GHC wrapper is provided:</p>
<pre><code>$ ghc ghclol.hs
</code></pre>
<h3>Strongly-connected components</h3>
<p>See <code>scc.hs</code> (and its GHC wrapper <code>ghcscc.hs</code>) for an elegant way to print the
strongly-connected components of a graph in reverse topological order.</p>
<pre><code>$ (./prog &lt; scc.hs ; cat prog.c) &gt; scc.c
</code></pre>
<p>It expects the input to be in a similar format as a previous entry
(2018 vokes). Indeed, obtain the 2018 winners, and run:</p>
<pre><code>$ ./scc &lt; 2018/vokes/example-1.txt
$ ./scc &lt; 2018/vokes/example-2.txt
</code></pre>
<p>The output should agree, though our program omits line numbers and does not
sort entries within a line. (Also, our program only treats spaces as
whitespace, and supports any nonspace character in a vertex name.)</p>
<h2>Syntax</h2>
<p>Some claim Haskell syntax is frightening because braces and semicolons are
optional. Some complain about a zoo of twisty little operators, all alike. Our
compiler addresses such concerns by making braces and semicolons compulsory,
disabling layout-based rules, making every operator left-associative with same
precedence, and only defining 6 primitive functions:</p>
<pre><code>: + - * / &lt;=
</code></pre>
<p>The arithmetic operations behave as they do in C on unsigned ints, and <code>(:)</code> is
Haskell&rsquo;s cons function. Like Haskell and unlike C, <code>(&lt;=)</code> returns a Bool
(which are Church booleans behind the scenes) and not an Int.</p>
<p>No ifs, ands, or buts. Define them yourself. No tuples. Who needs them when
algebraic data types delivers a better product? There is no do. No where. No
list comprehensions. No unary operators.</p>
<p>Let expressions and operator sections are supported.</p>
<p>Within global scope or a let expression, each definition can only refer to
itself or previous definitions. This implies we can only achieve mutual
recursion by having one function pass itself to others.</p>
<h2>Caveats</h2>
<p>The only primitive type is <code>Int</code>. In particular, they represent characters. To
interoperate with GHC, our compiler treats any undefined functions as the
identity function, so that we may freely use <code>ord</code> and <code>chr</code> (or <code>fromEnum</code> and
<code>toEnum</code>) to make our code acceptable to both compilers.</p>
<p>The main function is the last function to successfully parse. It should have
type <code>[Int] -&gt; [Int]</code>, and our compiler treats this like the function passed
into <code>Prelude.interact</code>, that is, the entire standard input is passed to this
function, and the result is printed to standard output.</p>
<p>Bool must be defined as:</p>
<pre><code>data Bool = True | False;
</code></pre>
<p>so that it matches the Scott-encoded booleans internally used by the primitive
function <code>(&lt;=)</code>.</p>
<p>The alternatives in a case expressions must list every data constructor in
the order they are defined. For example, if we have:</p>
<pre><code>data Foo a b = Bar a | Baz | Qux Int [b]
</code></pre>
<p>then a case expression that examines a term of this type must have the form:</p>
<pre><code>case x of
{ Bar a -&gt; ...
; Baz -&gt; ...
; Qux n bs -&gt; ...
}
</code></pre>
<p>We stress braces and semicolons are required. Our fussy parser treats
semicolons as separators, not terminators.</p>
<p>The effect of erroneous input is undefined. It may be best to develop with GHC,
but even then, be mindful of changes needed because of issues caused by the
uniform operator precedence and the touchy format of case alternatives.</p>
<h2>Why?</h2>
<p>One-letter variable names abound in IOCCC entries, and for good reason. These
tiny pieces of confetti are hard to read, and leave room for more code. Then
why not go further and use zero-letter variable names? That is, tacit
programming or point-free style.</p>
<p>I had been playing with an algorithm devised by Oleg Kiselyov that effortlessly
and efficiently eliminates those pesky variables, leaving behind terms composed
from a small set of combinators. No need for lambda lifting or supercombinators.</p>
<p>By adding a handful of lines of mostly parsing code, we get a Haskell compiler,
or rather, a compiler that accepts a subset of Haskell sufficiently large to
self-host. You might say I wrote a tool for this contest, then ran it on itself
to make an entry for it.</p>
<h2>Obfuscation techniques</h2>
<p>Even with Kiselyov&rsquo;s algorithm and some term rewriting, the compiler only fit
after compression, which naturally obfuscates the code. More tricks were needed
to fit within the size limits.</p>
<ul>
<li>One-letter variables, until enough is done to banish variables completely.</li>
<li>Ipse dixit. Near the end, the code declares itself to be an obfuscated
program. (There is also an exhortation intended for the judges in a similar
format earlier in the source.)</li>
<li>Typical C mischief: pre- and post-increment, commutative array indexing,
ternary operators, and so on.</li>
<li>Huffman coding.</li>
<li>Base-85 because high bits are frowned upon.</li>
<li>Mixed radix encoding to game iocccsize. From a past winner (2018 bellard),
it seems 9 11 12 32 are the only whitespace octets that may appear verbatim in
string literals.</li>
<li>Choosing what to encode in Huffman/base-85 and what to encode in mixed radix
was a delicate balancing act. In the end, I only had a few bytes to spare,
which I spent on gratuitous confusion.</li>
<li>The effects of some functions depend on the order their arguments are
evaluated, yet the program works either way. Why?</li>
<li>Ugly macros for the runtime system&rsquo;s jump table for lazy reduction. A
previous winner (2013 endoh1) has a cuter solution, which I avoid because of
originality concerns and also because my combinators are compressed.</li>
<li>Relies on the inability of C comments to nest.</li>
<li>Cheaper and more complicated to print comma-separated ints (and header and
footer) in C.</li>
<li>Primitive functions use a trick described in depth by <a href="https://www.cs.york.ac.uk/fp/reduceron/jfp-reduceron.pdf">Naylor and Runciman,
&ldquo;The Reduceron reconfigured and
re-evaluated&rdquo;</a>. We
represent the integer n with a term equivalent to <code>Y(BT)n</code>; it works because
<code>Y(BT)ne = e(Y(BT)n)</code>.</li>
<li>A sentinel in the heap often confused me, so ought to confuse others.</li>
</ul>
<p>Other obfuscation techniques are better appreciated after decoding the
compiler. See <code>hint.hs</code>.</p>
<ul>
<li>Mercilessly point-free. Everything is a combinator.</li>
<li>Scott encoding. Everything is a combinator.</li>
<li>Sum types are oddly ordered and may even contain unused data constructors
to reduce code duplication. (In C terms, unions may have extra fields, and
they&rsquo;re ordered in such a way so we can reuse code to access certain fields.)</li>
<li>The <code>undefined</code> function compiles to the <code>(.)</code> function.</li>
<li>Replaced the only <code>(&amp;&amp;)</code> with <code>(||)</code> and <code>not</code> using De Morgan&rsquo;s law, which
makes some comparisons less comprehensible.</li>
<li><a href="http://okmij.org/ftp/tagless-final/ski.pdf">Kiselyov only published &ldquo;&#955; to SKI, Semantically&rdquo; last
year</a>.</li>
<li>Recursion via the fixpoint (Y) combinator, which is represented by the
variable &ldquo;&rdquo; during one stage of compilation.</li>
<li>Involves theory that may be less familiar to C programmers: maps, folds,
parser combinators, lambda calculus, bracket abstraction, denotational
semantics, etc.</li>
</ul>
<h2>Warnings</h2>
<p>On my system, it compiles cleanly with <code>-Wall</code> with older standards, e.g.
<code>-std=c89</code>, but less cleanly if <code>-pedantic</code> is also supplied.</p>
<p>Compiling the compiler output with <code>-Wall</code> triggers a warning about a
strange-looking comment.</p>
<h2>Behind-the-scenes commentary</h2>
<p><a href="https://crypto.stanford.edu/~blynn/compiler/ioccc.html">My website reveals how this compiler
works.</a></p>
<hr />
<TABLE><TR>
<TD><a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="/png/by-sa-3.0-88x31.png" /></a></TD>
<TD><P>&copy; Copyright 1984-2019,
<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="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
<TD>&nbsp;<!--<a href="https://validator.w3.org/check?uri=referer"><img src="https://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
</TR></TABLE>
</body>
</html>
-651
View File
@@ -1,651 +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.2.0">
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8"> <link rel="stylesheet"
type="text/css"
href="../hint.css">
<title>Most in need to be tweeted</title>
</head>
<body>
<h1>Most in need to be tweeted</h1>
<p>Christopher Mills<br>
Twitter: @MisterXopher</p>
<h2>Judges' comments:</h2>
<h3>To use:</h3>
<pre><code>make
make cpclean
# Let this run for about about an hour and then kill it
./prog Shakespeare.txt
./prog &lt; $(&lt; ls -1tr cp* | tail -1) | head -100
</code></pre>
<h3>Try:</h3>
<pre><code># If you are on a 64-bit system:
make test-64bit
less IOCCC-Rules-Guidelines.output.txt
less IOCCC-hints.output.txt
less Eugene_Onegin.output.txt
# However, as the binary model files used to produce the output are in an implementation-specific format,
# your mileage may vary.
</code></pre>
<h3>Selected Judges Remarks:</h3>
<p>Can a machine learn?</p>
<p>Some say so.</p>
<p>But can a machine learn to write like Shakespeare,</p>
<p>or tweet like <a href="http://trumptwitterarchive.com">Trump</a>?</p>
<p>Can it write rules and guidelines for the IOCCC?</p>
<p>You decide. :-)</p>
<h2>Author&rsquo;s comments:</h2>
<h1>Welcome to OMLET! &#x1f373;</h1>
<p>OMLET is the <em>Obfuscated Machine Learning Environment Toolkit</em>, a
micro-framework for experimenting with <a href="https://en.wikipedia.org/wiki/Recurrent_neural_network">recurrent neural networks</a>. OMLET
lets you build, train and evaluate <a href="https://en.wikipedia.org/wiki/Deep_learning">deep neural networks</a>. Why invest
hours reading documentation and megabytes of disk space on a full-featured DNN
framework like <a href="https://www.tensorflow.org">TensorFlow</a> or <a href="http://torch.ch">Torch</a> when you can have full RNN
functionality in less than 4 KB!</p>
<p>OMLET has the following features:</p>
<ul>
<li>User-programmable network configurations and hyperparameters</li>
<li>Support for various types of recurrent and feed-forward neural networks
including vanilla RNNs, LSTMs and GRUs of depths of up to 99 layers</li>
<li>No limit on parameter size (except for those imposed by the system)</li>
<li>Training and inference modes, with periodic checkpointing</li>
<li>Advanced <a href="https://arxiv.org/abs/1412.6980">Adam</a> optimizer with <a href="https://www.fast.ai/2018/07/02/adam-weight-decay/">weight decay</a> for simplified
training</li>
<li>Hyperparamer support for batch sizing, learning rate schedule, weight
decay and gradient clipping</li>
<li>Easily extensible (requires some expertise in the C programming language)</li>
<li>Friendly markdown documentation</li>
</ul>
<p>OMLET is based on <a href="https://cs.stanford.edu/people/karpathy/">Andrej Karpathy&rsquo;s</a> <a href="https://github.com/karpathy/char-rnn">character-level language model</a>
as described in his blog post <a href="http://karpathy.github.io/2015/05/21/rnn-effectiveness/"><em>The Unreasonable Effectiveness of Recurrent
Neural Networks</em></a>. I&rsquo;ve included a small sample dataset to use for
training, but you can have even more fun by downloading some larger datasets:</p>
<ul>
<li><a href="https://cs.stanford.edu/people/karpathy/char-rnn/linux_input.txt">Linux kernel source</a></li>
<li><a href="https://cs.stanford.edu/people/karpathy/char-rnn/warpeace_input.txt"><em>War and Peace</em></a></li>
<li><a href="https://github.com/ryanmcdermott/trump-speeches">Donald Trump&rsquo;s 2016 campaign speeches</a></li>
</ul>
<h2>Getting started with OMLET</h2>
<p>OMLET has three operating modes:</p>
<ul>
<li><em>Training</em>, which trains a network from scratch</li>
<li><em>Continuation</em>, which trains starting from an existing checkpoint</li>
<li><em>Inference</em>, which uses an existing trained network to make predictions</li>
</ul>
<p>For your first OMLET experiment, we will try training a simple single-level
RNN to write some <a href="https://en.wikipedia.org/wiki/William_Shakespeare">Shakespere</a> plays. Start by typing</p>
<pre><code>make
</code></pre>
<p>After it builds, train it using</p>
<pre><code>./prog shakespere.txt
</code></pre>
<p>This will immediately start outputting gibberish to the output, e.g.</p>
<pre><code>./prog shakespere.txt
sins ohennAu
T-teooclelp tiThoWy
g
nlakuafy
e
sselW usnsofueB Aoee pasfUsuslhe ooM ot Wou moy
me neltAl -no IoyI mhuyakse inT-l chu ghenn ffo? fnsoe yhyye
ue nnfrlass heUthole saounlcesyee pee
t,
T0:0% 3.210888
o',,vU
An ,hTf lnm Far rur:s moilt WoEgrv wonds mith Aog thernw
Rni So
co Nnd :
For an bImy pgafoun:
Wf'r hom wortiverita
int fod mous Eheledet,
Tho he theket nonS wnu-ang dorlaMSp
nrocWiSe tflg 'o.
T0:0% 2.995950
d whecedhencrysesil yr bn,
we hh y thiwt
hut fithlot,
Fmdy s he alt
Vh th no dh foud bobt werw:s Aotnf Fhwi't whe, eusu
lhh thele wewcond ary soupfy wind tDont couc ths:
er fucwald oncli hen bos, f
T0:1% 2.878945
</code></pre>
<p>The gibberish is the networks attempt to write a play. So far, it&rsquo;s not very
successful! Between the chunks of gibberish are training progress reports
that look like</p>
<pre><code>T0:1% 2.878945
</code></pre>
<p>This tells you that we are 1% through training epoch 0, and that the training
<a href="https://en.wikipedia.org/wiki/Loss_function">loss</a> is about 2.88. As the training continues, the training loss will
reduce and the generated snippets will improve quickly:</p>
<pre><code>ses, kuth
LAs of the wish,
As, I nos you,
Yov not to nalll,
Tr tot wonds.
First Sondy, llt lrte, our, tw.
First.
BRUTUS:
Helsting the kith gops of hoch Whay, fars surd what to,
The cownens golt te.
T0:12% 2.259114
eplerrotrur tandans one wiok thy or thach and cullice ded yourssting
And wours:
Whed ur surt.
SINENIUS:
On we lain bith
rerytund: tich lon hyivetetgor.
VOLUONIA:
He brich nom dove worthan then wise,
T0:13% 2.254926
</code></pre>
<p>It&rsquo;s already started to figure out things about Shakespere plays &ndash; how to
spell short English words, how long lines tend to be, and that characters take
turns speaking with their names capitalized. The training loss has dropped to
2.25 and the improvement is noticeable.</p>
<p>Eventually, we will finish with the training data set and move on to a
validation cycle:</p>
<pre><code>y fath onother,
I sucess,
For I me the west crare.
TRANIO:
Whow and'd have not to had you you one in my lapteny she very ame come me a gut and shourd aghir you as ignested; shend to make I strem
To h
T0:99% 1.924063
notnce gaud and is nicked thou day, ha the dusing you disaid: in thim, you things in ere thee thus erile Iht that tare theme my hast thesp thou shay: thou not eaten-or-ho-bess resing: I the but had d
T0:99% 1.923128
V0:0% 1.678907
V0:9% 1.700527
V0:18% 1.733179
V0:27% 1.714891
V0:36% 1.716672
V0:45% 1.782946
V0:54% 1.835629
V0:63% 1.876108
V0:72% 1.906814
V0:81% 1.924096
V0:90% 1.954492
V0:99% 1.969287
serfs you'll alliencseard:
We
got you? before
I say.
Farstred dentlentecaly, sir, I it one bosticield
All me the backnour mino,
Whith capitaned mid! but stell the ifvemion
Willerity.
First Cumfol of
T1:0% 1.885619
</code></pre>
<p>Validation cycles are used to test the network to see if it has learned to
generalize &ndash; how well performs on data it hasn&rsquo;t seen before (as opposed to
the training data that the network will see many times as it trains). Progress
on the validation set is also displayed with a validation progress report that
looks like</p>
<pre><code>V0:36% 1.716672
</code></pre>
<p>which means we are 36% of the way through the validation for epoch 0, and the
validation loss is about 1.72. Comparing the validation loss and the
training loss will give you an idea of how well the network is learning and
can let you know if the network is <a href="https://en.wikipedia.org/wiki/Overfitting">overfitting or underfitting</a>.</p>
<p>As part of the training process, the data set (which for OMLET is the
<code>shakespere.txt</code> file you gave on the command line) is divided into
<a href="https://en.wikipedia.org/wiki/Training,_validation,_and_test_sets">training and validation sets</a> (by default, 95% of the data is used for
training, but like most OMLET parameters, you can change this at compile-time).</p>
<p>At the end of the validation run, OMLET writes out a checkpoint file with a
name like <code>cp01_1.970</code>. This saves the state of the run at the start of the
epoch 1, after computing a validation loss of 1.970. The checkpoint is
helpful if you need to stop and restart training. You can stop training by
doing <code>Control-C</code>.</p>
<p>You can continue training from a previous checkpoint by providing the
checkpoint file name as the second parameter, for example:</p>
<pre><code>./prog shakespere.txt cp01_1.970
</code></pre>
<p>After the validation cycle finishes, OMLET begins the next epoch by restarting
training at the beginning of the training set. Training continues forever,
until you quit it with <code>Control-C</code>. You should monitor the checkpoints to
see that the validation loss continues to drop. If it rises, the network has
probably started to overfit on the training data.</p>
<p>Once you&rsquo;ve trained the validation loss as low as it will go, you can use
OMLET to run the network in inference mode which uses the frozen checkpoint
parameters to generate data. Inference mode takes the checkpoint file as
<em>standard input</em> (not on the command line) and hence must be run with a
command like</p>
<pre><code>./prog &lt; cp55_1.807
</code></pre>
<p>Running it produces an infinite amount of generated output, until you hit
<code>Control-C</code> to stop it.</p>
<p>Note that if you decide to change networks or use a different input file, you
will want to delete all the checkpoint files because the format depends on
both the network and the input &ndash; using the wrong checkpoint is likely to
cause a crash.</p>
<h2>Experimenting with different networks</h2>
<p>The default network for OMLET (the one you get if you type <code>make</code> with the
executable name <code>prog</code>) is the simplest recurrent neural network. It looks
like</p>
<pre><code>h = tanh(Wxh * x + Whh * h' + Bh)
y = Why * h + By
</code></pre>
<p>where</p>
<ul>
<li><code>x</code> is the <em>input vector</em></li>
<li><code>y</code> is the <em>output vector</em></li>
<li><code>h</code> is the <em>hidden state vector</em></li>
<li><code>h'</code> is the previous value of <code>h</code></li>
<li><code>Wxh</code>, <code>Whh</code>, and <code>Why</code> are <em>weight matrices</em></li>
<li><code>Bh</code> and <code>By</code> are <em>bias vectors</em>.</li>
<li><code>tanh</code> is the <a href="https://en.wikipedia.org/wiki/Hyperbolic_function">hyperbolic tangent function</a></li>
</ul>
<p>The <code>W</code>&rsquo;s and <code>B</code>&rsquo;s are the trainable parameters of the network, and the
process of training is optimizing the values of these parameters to minimize
the loss of the network across the training set.</p>
<p>It is the presence of the hidden state vector that allows the RNN to
&ldquo;remember&rdquo; the past. We can see what would happen if we removed this hidden
state. If you type</p>
<pre><code>make lin1
</code></pre>
<p>OMLET will create an <a href="https://en.wikipedia.org/wiki/ADALINE">ADALINE</a> network that does</p>
<pre><code>y = Wxy * x + By
</code></pre>
<p>This simple <a href="https://en.wikipedia.org/wiki/Linear_map">linear</a> <a href="https://en.wikipedia.org/wiki/Feedforward_neural_network">feed-forward network</a>. You can run it with</p>
<pre><code>./lin1 shakespeare.txt
</code></pre>
<p>The linear network won&rsquo;t be able to get past the gibberish stage, because it
lacks history:</p>
<pre><code>./lin1 shakespeare.txt
UERond w,
Gir:
KINof s, mesther s thouth.
E:
KINTret, at fu,
GOMy t, as sth kesewit sooos atse ang k, ck,
Sotheouserivesthecowhet been's, t he, h nre; t and, har wiread of pincer cedst sur has, ut:
T14:67% 2.465115
UKESpan,
NGaromy soreate e m esewfoure pamitherarjulthengeoly tl.
NG s at e! w.
WAllinoully?
Wamisw ofilem:
I'delandinarrstath har aksubly s cath Whern t Is, weciss:
GLat s; llde.
Y aterit dsthence
T14:67% 2.465404
</code></pre>
<p>It is able to guess at what character is likely to follow the current one
(by doing a <a href="https://en.wikipedia.org/wiki/Linear_regression">linear regression</a>), but it lacks any history beyond that to
guide it.</p>
<p>You might be wondering about the role of the <code>tanh</code> function in the RNN.
<code>tanh</code> acts as an <a href="https://en.wikipedia.org/wiki/Activation_function">activation function</a> which adds <a href="https://en.wikipedia.org/wiki/Nonlinear_system">nonlinearity</a>
to the network and allows it to solve complicated problems. Without
nonlinearity, all of the linear functions would fold together into a single
matrix-vector multiply and you&rsquo;d effectively regress to the linear network
above. Alas, even adding a nonlinearity to the feed-forward network
(creating a <a href="https://en.wikipedia.org/wiki/Perceptron">perceptron</a>) does not improve the performance because we
still lack the history provided by the hidden state vector (although if you
want to try it yourself, you can do so with <code>make per1</code>).</p>
<h2>Going deeper</h2>
<p>We can try to improve the RNN&rsquo;s performance by stacking RNN modules atop each
other:</p>
<pre><code>h1 = RNN(h1', x)
h2 = RNN(h2', h1)
y = Why * h2 + By
</code></pre>
<p>with <code>RNN(h, x)</code> defined as above. Each RNN module has its own set of
parameters and its own hidden state vector. This will improve the network&rsquo;s
performance, at the cost of a much larger parameter space</p>
<blockquote><p><strong>IMPORTANT NOTE</strong>: Since OMLET uses the system stack for network storage,
larger networks may cause OMLET to crash (typically with a message like
<code>Segmentation fault</code>) unless the system stack size is first increased.
The exact command for doing so depends on your shell and your system&rsquo;s
hard limits. On <code>sh</code>/<code>ksh</code>/<code>bash</code> shells, you can view the hard limit
with <code>ulimit -Hs</code> and set it with <code>ulimit -s 65532</code> (replacing <code>65532</code>
with the actual hard limit). On <code>csh</code>/<code>tcsh</code> shells, you can view
the hard limit with <code>limit -h stacksize</code> and set it with
<code>limit stacksize 65532</code> (replacing <code>65532</code> with the actual hard limit).</p></blockquote>
<p>You can try the deeper network by doing</p>
<pre><code>make rnn2
</code></pre>
<p>(or even <code>make rnn3</code> if you want a three-layer RNN) and train it with</p>
<pre><code>./rnn2 shakespeare.txt
</code></pre>
<p>The additional depth should allow the network to make better predictions (it
can represent more complicated history), but it may take a long time to train
&ndash; both because the network (being larger) now requires more time to train and
because of the <a href="https://en.wikipedia.org/wiki/Vanishing_gradient_problem">vanishing and exploding gradient problem</a>, which might
keep it from ever reaching its potential.</p>
<h2>LSTMs and GRUs</h2>
<p>RNNs are particularly hard to train because the they are trained using
<a href="https://en.wikipedia.org/wiki/Backpropagation_through_time">bankpropagation through time</a>. The RNN is trained by effectively
converting it into a non-recurrent network by making many copies of it
and propagating the hidden state through the copies. During training,
the backpropagation through many clones of the network amplifies the
gradient, worsening the exploding and vanishing gradient problem.</p>
<p><a href="https://en.wikipedia.org/wiki/Long_short-term_memory">Long Short Term Memory</a> networks (also called LSTMs) were developed to
solve this problem. Christopher Olah gives a good description of them
at his <a href="http://colah.github.io/posts/2015-08-Understanding-LSTMs/">blog posting</a>. You can build a two-level LSTM by doing</p>
<pre><code>make lstm2
</code></pre>
<p>and train with it with</p>
<pre><code>./lstm2 shakespeare.txt
</code></pre>
<p>The LSTM is much easier to train because it explicitly decides how to update
its hidden state via &ldquo;gates&rdquo;. These gates are called</p>
<ul>
<li><em>input gate</em>, which decides what part of the input to pay attention to</li>
<li><em>forget gate</em>, which decides what part of the hidden state to forget</li>
<li><em>output gate</em>, which decides what part of the hidden state is used to
produce the output</li>
</ul>
<p>The basic LSTM equations are</p>
<pre><code>f = sigmoid(Wxf * x + Whf * h' + Bf)
i = sigmoid(Wxi * x + Whi * h' + Bi)
o = sigmoid(Wxo * x + Who * h' + Bo)
c = f * c' + i * tanh(Wxc * x + Whc * h' + Bc)
h = o * tanh(c)
</code></pre>
<p>Where</p>
<ul>
<li><code>x</code> is the input vector</li>
<li><code>h</code> is the hidden state (and the output to the next layer)</li>
<li><code>c</code> is the <em>cell state</em> which represents the &ldquo;memory&rdquo; of the LSTM</li>
<li><code>h'</code> and <code>c</code>&lsquo; are the previous values of <code>h</code> and <code>c</code> respectively</li>
<li><code>f</code> is the <em>forget gate</em> that tells the LSTM what portion of the hidden
state to forget</li>
<li><code>i</code> is the <em>input gate</em> that tells the LSTM what portion of the input
vector to pay attention to</li>
<li><code>o</code> is the <em>output gate</em> that tells the LSTM what portion of the cell
state to use to generate the hidden state</li>
<li><code>Wxf</code>, <code>Whf</code>, <code>Wxi</code>, <code>Whi</code>, <code>Wxo</code>, <code>Who</code>, <code>Wxc</code>, and <code>Whc</code> are trainable
parameter matrices</li>
<li><code>Bf</code>, <code>Bi</code>, <code>Bo</code>, and <code>Bc</code> are trainable bias vectors</li>
<li><code>tanh</code> is the hyperbolic tangent function</li>
<li><code>sigmoid</code> is the <a href="https://en.wikipedia.org/wiki/Logistic_function">logistic function</a></li>
</ul>
<p>There are several LSTM variants (see <a href="http://colah.github.io/posts/2015-08-Understanding-LSTMs/">C. Olah&rsquo;s blog post</a> for more
examples). One important one is the <a href="https://en.wikipedia.org/wiki/Gated_recurrent_unit">gated recurrent unit</a>. GRUs are
simplified versions of an LSTM which combine the gates together, meaning they
require fewer learned parameters. This allows them to train faster than a
generic LSTM. You can build a two-layer GRU with</p>
<pre><code>make gru2
</code></pre>
<h2>Building your own networks</h2>
<p>The OMLET <code>Makefile</code> comes with one-, two- and three-layer RNNs, LSTMs and
GRUs, along with simpler feed-forward networks like multi-layer perceptrons and
a linear network. This isn&rsquo;t the limit of OMLET&rsquo;s power &ndash; you can create your
own networks by modifying the <code>Makefile</code>. Networks are passed in on the
compiler&rsquo;s command-line by using <code>-D</code> directives. The network is defined by
a <code>-DNW='...'</code> command which consists of a series of comma-separated
assignments. For example, the simple one-layer RNN could be defined like</p>
<pre><code>-DNW=` x = I(n), hp = I(128), \
h = C(hp, T(A(L(128, x), L(128, hp)))), \
y = L(n, h)'
</code></pre>
<p>The network declares <code>x</code> as an input vector (there must be a declaration for
<code>x</code>). It is declared as <code>I(n)</code>, which is an input vector of size <code>n</code>, which
is the number of characters of the input alphabet (OMLET computes this from
the input file at the start of training). OMLET will arrange to present the
input character as a <a href="https://en.wikipedia.org/wiki/One-hot">one-hot</a> vector based on the current input
character.</p>
<p>The second declaration, <code>hp</code>, declares the previous hidden state vector (what
we called <code>h'</code> above). We declare this to be of size 128 &ndash; an arbitrary
choice. A larger state vector can (theoretically) carry more state, but at
a cost of larger parameter matrices and longer training time. You can
experiment with increasing the hidden vector size and see.</p>
<p>The third line is the core of the RNN. It sets <code>h</code>, the hidden vector output
to be the sum of two linear elements specified by <code>L</code>. The <code>L</code> function
takes two parameters &ndash; the output vector size (which must match the size of
<code>h</code>) and the input vector. <code>L</code> will compute <code>y = W * x + B</code> where each <code>L</code>
has its own <code>W</code> (weight) and <code>B</code> (bias) training parameters. Both <code>x</code> and
<code>hp</code> are sent through <code>L</code> and the result passed through the <code>A</code> function,
which does vector addition. That result is passed through <code>T</code> which does
element-wise <code>tanh</code> activation.</p>
<p>Next, we wrap the whole thing with the <code>C</code> function. <code>C</code> connects <code>hp</code>
with <code>h</code>, causing the new value of <code>h</code> to be passed to the <code>hp</code> vector on
the next iteration of the algorithm (allowing the RNN to retain state in <code>h</code>).</p>
<p>Finally, the whole result is passed through another instance of <code>L</code>, this time
producing a vector of size <code>n</code>, which will have the negative log
<a href="https://en.wikipedia.org/wiki/Likelihood_function">likelihood</a> function. This is assigned to <code>y</code>, which is the output of
the network (and hence must also be declared).</p>
<p>OMLET will take the <code>y</code> result and pass it through the <a href="https://en.wikipedia.org/wiki/Softmax_function">softmax</a> function,
which converts the log probabilities into a probability distribution. In
inference mode, this is used to select the next character to emit. In
training mode, this is used to generate the loss which is backpropagated.</p>
<p>As an example of a more complicated network, we can look at a two-layer
GRU network:</p>
<pre><code>-DHS=128, \
-DNW=' x = I(n), \
y = L(n, MD(MD(x)))' \
-DBK=' hp = I(HS), \
z = S(A(L(HS, x), L(HS, hp))), \
r = S(A(L(HS, x), L(HS, hp))), \
c = T(A(L(HS, x), L(HS, hp))), \
zc = OG(1, -1, z), \
h = C(hp, A(M(zc, hp), M(z, c))), \
y = h'
</code></pre>
<p>We are using a few new tricks here &ndash; first, we are defining <code>HS</code> as the size
of the hidden and cell vectors. There&rsquo;s nothing special about this name, its
just convenient to specify it so we don&rsquo;t have a bunch of constants in the
code. Second, the network itself is very simple &ndash; it declares <code>x</code> and has
the matrix that converts the <code>HS</code>-sized hidden vector back to the <code>n</code>-sized
alphabet vector&hellip; but it now calls <code>MD</code>, which is the user-definable
module (here we are using it twice, to have two cascaded GRU blocks). The
<code>MD</code> function performs the sub-network defined by the <code>BK</code> compile-time
parameter (specified in the <code>-DBK='...'</code> setting). This sub-module again
takes an <code>x</code> parameter and produces a <code>y</code> output. Inside it, we declare
<code>hp</code> and <code>h</code>, the previous and current state vector, plus equations for the
various GRU gates (these use <code>S</code> for the sigmoid activation function).
One final new call is <code>OG</code> which does offset and gain, performing
<code>y = offset + gain * x</code> where <code>offset</code> (the first parameter) and <code>gain</code> (the
second) are constants. We are using this here to compute <code>(1 - z)</code> for the
GRU&rsquo;s linear interpolator.</p>
<p>The full set of available function blocks follows:</p>
<ul>
<li><code>I(s)</code>: declares a vector (input or state) of size <code>s</code></li>
<li><code>L(s, x)</code>: learnable linear function <code>y = W * x + B</code> with an output vector
size of <code>s</code></li>
<li><code>CM(x)</code>: learnable element-wise gain function <code>y = W * x</code></li>
<li><code>A(a, b)</code>: element-wise add: <code>y = a + b</code></li>
<li><code>M(a, b)</code>: element-wise multiply: <code>y = a * b</code></li>
<li><code>S(x)</code>: sigmoid activation function <code>y = sigmoid(x)</code></li>
<li><code>T(x)</code>: hyperbolic tangent activation function <code>y = tanh(x)</code></li>
<li> <code>C(xp, x)</code>: copy <code>x</code> to <code>xp</code> in the next time step (propagate through
time)</li>
<li> <code>OG(o, g, x)</code>: apply a constant offset and gain: <code>y = o + g * x</code></li>
<li> <code>MD(x)</code>: apply the sub-network specified by <code>BK</code></li>
</ul>
<p>Note: even if you don&rsquo;t use <code>MD</code> in your network, you should still define
<code>BK</code> by adding <code>-DBK='y=x'</code> to the command line, otherwise you will get a
compile-time error.</p>
<h2>Hyperparameters</h2>
<p>OMLET has a large number of training and inference parameters which can be
changed by the user. All of these are set by <code>-D</code> on the compile command line.
The list of hyperparameters follows:</p>
<ul>
<li><code>TP</code>: Temperature parameter for use in inference mode. This divides the
log probabilities before softmax. A low temperature makes the model choose
safer but more boring choices. A high temperature takes more risks but
makes more mistakes. Default is 1.0, which uses the computed
probabilities.</li>
<li>&lsquo;N&rsquo;: Batch size. This is the number of times the RNN is unrolled, so it
controls how far back in the past the RNN can see. The default is 50.
Larger batch sizes update the weights less frequently and allow the RNN to
see farther back in time, but at a cost of proportionally more memory.</li>
<li><code>TR</code>: The percentage of batches in the input data set that will be used
for training. The default value of 0.95 sets this as 95%.</li>
<li><code>LR</code>: The initial learning rate, The default is 0.002.</li>
<li><code>LE</code>: The epoch where the learning rate will start decaying. Defaults to
epoch 10.</li>
<li><code>LD</code>: Learning rate decay, per epoch (after <code>LE</code> epochs). The learning
rate is scaled by this number. Default is 0.97</li>
<li><code>WD</code>: Weight-decay parameter, to promote <a href="https://en.wikipedia.org/wiki/Regularization_(mathematics)">regularizaiton</a>. The default
is 0.00008.</li>
<li><code>RS</code>: The random scale for weight initialization. Weight parameters will
be initialized to be between <code>-RS</code> to <code>+RS</code>. The default is 0.15.</li>
<li><code>CL</code>: Clamp value for gradients. Gradients will be limited to the range
<code>-CL</code> to <code>+CL</code>. Default is 5.</li>
<li><code>B1</code>: Momentum mean parameter for Adam optimizer. Set to 0.9.</li>
<li><code>B2</code>: Momentum variance parameter for Adam optimizer, Set to 0.999.</li>
<li><code>EP</code>: Epsilon parameter for Adam, to provide numerical stability. Set to
0.00000001.</li>
<li><code>DI</code>: How often to print a training or validation progress message and
inference snippet. The default prints every 100 training batches.</li>
<li><code>SL</code>: The number of characters to print when doing an inference snippet.
Default is 200.</li>
<li><code>PF</code>: Format string for the checkpoint filename. The default is
<code>"cp%02d_%.3f"</code> which includes the epoch and validation loss. You may
wish to add a subdirectory to the name to keep checkpoint files out of
the current directory.</li>
</ul>
<hr />
<TABLE><TR>
<TD><a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="/png/by-sa-3.0-88x31.png" /></a></TD>
<TD><P>&copy; Copyright 1984-2019,
<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="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
<TD>&nbsp;<!--<a href="https://validator.w3.org/check?uri=referer"><img src="https://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
</TR></TABLE>
</body>
</html>
-185
View File
@@ -1,185 +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.2.0">
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8"> <link rel="stylesheet"
type="text/css"
href="../hint.css">
<title>Most calendrical</title>
</head>
<body>
<h1>Most calendrical</h1>
<p>Timo Poikola<br>
<a href="https://ig.fi/other/ioccc">https://ig.fi/other/ioccc</a><br>
Twitter: @timpoiko</p>
<h2>Judges' comments:</h2>
<h3>To use:</h3>
<pre><code>make prog
./prog 512 ./prog
sleep 86400; make clobber prog
./prog 512 ./prog
sleep 86400; make clobber prog
./prog 512 ./prog
</code></pre>
<h3>Try:</h3>
<pre><code>If you don't have a few days, try:
TZ=UTC24 make clobber prog
./prog 512 ./prog
TZ=UTC48 make clobber prog
./prog 512 ./prog
</code></pre>
<h3>Selected Judges Remarks:</h3>
<p>Do you have the time to see what this program does? Think again, come back and try again.</p>
<p>Note that 2 can be said to be the least odd prime because it is the greatest even prime.
Moreover 2 can be also said to be the greatest odd prime because it is the least even prime.</p>
<p>The source code layout and some of the variable names honors the ski jumping accomplishments of
<a href="https://en.wikipedia.org/wiki/Matti_Nyk%C3%A4nen">Matti Nyk&auml;nen</a>.</p>
<h2>Author&rsquo;s comments:</h2>
<h3>How to build</h3>
<pre><code>gcc -O0 -o prog prog.c
</code></pre>
<p>or</p>
<pre><code>clang -O[0123s] -o prog prog.c
</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>
<p>An old wise man mumbled to me:</p>
<blockquote><p>Implement a program, which can calculate SHA-3 checksum for a file</p></blockquote>
<p>I think it is easy, but the wizard didn&rsquo;t stop yet:</p>
<blockquote><p>and primes and Fibonacci numbers.</p></blockquote>
<p>Still easy. But the Gandalf the Grey impersonator is not ready:</p>
<blockquote><p>But use only <em>main()</em>, and do not use <em>math.h</em> nor predefined stuff at all. But wait, there are some more rules: This
work should reflect the extraordinary mind of Matti Nyk&auml;nen,
the all-time best <a href="https://en.wikipedia.org/wiki/Matti_Nyk%C3%A4nen">ski jumper</a> and
<a href="http://telefinn.blogspot.com/2011/11/matti-nykanen-quotes.html">amateur philosopher</a>, who passed away on fourth of
February 2019.</p></blockquote>
<h4>Oh boys.</h4>
<p>So, I followed the rules given by Gandalf the White and the Judges of IOCCC. Output of <code>iocccsize</code>,
using the <a href="/2019/iocccsize.c">2019 version of iocccsize</a>, is carefully selected.
For the sake of clarity, I used single letter variables in the code. I also avoided unnecessary use of functions.
Like a tripundra, this program has three levels. In order to reveal all of them, you have to compile this program
on three consecutive days.</p>
<p>As this is a contest for obfuscated code, the program does not perform unnecessary checks, but either fails or gets
stuck if invoked erroneously. The program is invoked in this way: ./prog <code>&lt;integer&gt;</code> <code>&lt;file&gt;</code> in where <code>&lt;integer&gt;</code> is
224, 256, 384, 512 or even 1024. Yes, I know 1024 is not a supported length of output, but as I said, the program does
not validate its input in any way. These same parameters should be given in calculating a Fibonacci sequence or prime
numbers. <em>Please note that maximum file size is one gigabyte.</em></p>
<h3>Obfuscation</h3>
<p><em>Matti Nyk&auml;nen</em>: Every time I jump, and I get that feeling of <em>bon voyage</em>, the feeling that I&#8217;ve been here
before.</p>
<p><em>Matti Nyk&auml;nen</em>: When you are about to jump, you are all alone and have to make your own decisions. Up there,
it&rsquo;s all <em>up yours</em>.</p>
<p>This code has some jumping too. I used some <code>goto</code>s instead of <code>longjmp()</code>. Some Finnish ski jumping sites are
used as labels, however, there is <code>lahti</code> instead of <tt style="font-family: Monaco, Courier New, monospace;font-size:
12px;">salpausselk&auml;</tt>.</p>
<h3>SHA-3-512 Compatibility chart</h3>
<p>Tested against <a href="https://www.di-mgt.com.au/sha_testvectors.html">test vectors</a>.
Clang-4.0: For optimization levels [0123s], the program compiles and produces correct output for every tested vector using
c11, c89, c90, c99, gnu11, gnu1x, gnu89, gnu90, gnu99, iso9899:1990, iso9899:199409, iso9899:1999 and
iso9899:2011 as argument of <code>-std=</code></p>
<p>Gcc-6: For optimization level 0, correct output using
c11, c99, gnu11, gnu1x, gnu89, gnu90, gnu99, iso9899:1999 and iso9899:2011</p>
<h3>Missing a prime</h3>
<p>For obvious reason, the oddest prime is missing from output.</p>
<h3>Observations</h3>
<p>Gcc and clang are very fragile compilers. I spent numerous hours trying to achieve exactly the same output from
different optimization levels and compilers. Small change in code can produce really unexpected results, i.e. the compiler
can skip a few expressions or statements without obvious reason.</p>
<h3>Major spoilers</h3>
<p>Please scroll down if you want to see spoilers.</p>
<div style="margin-bottom:61em;">&nbsp;</div>
<p>It is commonly believed that <a href="http://www.cadaeic.net/calendar.htm">Mike Keith&rsquo;s algorithm</a> published in <em>Journal of
Recreational Mathematics</em>, Vol. 22, No. 4, 1990, p. 280, is the shortest way to calculate weekday for given date.
Keith&rsquo;s algorithm:<br>
<code>(d+=m&lt;3?y--:y-2,23*m/9+d+4+y/4-y/100+y/400)%7</code><br>
My algorithm: I noticed that<br>
<code>(23*m/9+(m&lt;3?y--:y-2)+d+4+y/4-y/100+y/400)%7</code><br>
is one character shorter. In my solution, <code>m&lt;3?y--:y-2</code> is used directly, instead of assign value for <code>d</code>.</p>
<p>Q is pronounced in Finnish exactly like &ldquo;kuu&rdquo;, a word for month or the Moon. So, <code>Q = k</code> is intended.</p>
<p>Last term of outputted Fibonacci sequence is the last one smaller than 2<sup>64</sup>. It is plain coincidence (but a funny)
that value of &lsquo;^&rsquo; is 94 in ASCII table.</p>
<p>For prime calculations: I recycled code from my high school C-programming course. Originally, I wrote it over 20 years
ago. My teacher said that it is (too) complicated to use bits stored in arrays, so I did it.</p>
<h3>Other stuff</h3>
<p>Cody: I really like that you enjoyed my previous entry. I hope that you will like this entry too.
Because I did not want to give too many clues to Judges, I tried to write this entry in a different way
than Most Stellar, but in this code there is at least one recycled thing from it. By the way,
answers to questions: 1. 255. 2. Try to compare binary representations of those floats and binary representation
of the string &ldquo;25th IOCCC!&rdquo;. 3. I don&rsquo;t know. I used standard trigonometric functions from <code>math.h</code> for rotating the Big Dipper
and later replaced those functions with my own implementations. But there was a bug in my code and the effect was more
beautiful than intended. I did not even debug this bug and now it works as a feature. 4. It is not possible. If you
change a single bit, the Fletcher 16 checksum does not match anymore and <code>goto</code> jumps to end of the code.</p>
<p>I see that <em>Volker Diels-Grabsch</em>&rsquo;s winner is awarded in category <strong>Most self-aware</strong>. In last year, my entry incorporates
the Fletcher 16 algorithm to ensure integrity of code. One of my first ideas for this year was to do the same thing,
but with SHA-3. Using Fletcher 16, calculating a checksum which matches with <code>sleeping time factor</code> took about one minute.
I realized that SHA-3 even with 224-bit output could take too much CPU time.</p>
<p>I would like to say <em>thanks</em> to PSP, because there were not too much interrupts during the coding phase.</p>
<hr />
<TABLE><TR>
<TD><a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="/png/by-sa-3.0-88x31.png" /></a></TD>
<TD><P>&copy; Copyright 1984-2019,
<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="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
<TD>&nbsp;<!--<a href="https://validator.w3.org/check?uri=referer"><img src="https://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
</TR></TABLE>
</body>
</html>
-229
View File
@@ -1,229 +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.2.0">
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8"> <link rel="stylesheet"
type="text/css"
href="../hint.css">
<title>Most in need of transparency</title>
</head>
<body>
<h1>Most in need of transparency</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
./prog sample_input.txt a b c d
cat a
cat b
cat c
cat d
cat a b c d | ./prog
</code></pre>
<h3>Try:</h3>
<pre><code>./prog prog.c a b c d e
cat a
cat b
cat c
cat d
cat e
cat a b c d e | ./prog
cat a b c d e | ./prog | diff - prog.c
</code></pre>
<h3>Selected Judges Remarks:</h3>
<p>Do you understand how this program works?
You may have to go over and over the output again.</p>
<h2>Author&rsquo;s comments:</h2>
<h1>Summary</h1>
<p>Scramble/unscramble to single file:</p>
<pre><code>./prog original.txt &gt; scrambled.txt
./prog &lt; scrambled.txt &gt; unscrambled.txt
</code></pre>
<p>Scramble/unscramble to multiple files:</p>
<pre><code>./prog input.txt output1.txt output2.txt ...
cat output1.txt output2.txt ... | ./prog &gt; unscrambled.txt
</code></pre>
<p>Re-scramble:</p>
<pre><code>./prog original.txt | ./prog - &gt; scrambled1.txt
./prog original.txt | ./prog - | ./prog - &gt; scrambled2.txt
./prog original.txt | ./prog - | ./prog - | ... &gt; scrambled3.txt
</code></pre>
<p>Scramble slowly:</p>
<pre><code>./prog input.txt | ruby prog.c
</code></pre>
<p>Input must be in UTF-8 encoding.</p>
<h1>Details</h1>
<p>This is a text scrambling utility. To scramble text, specify input
file name as the first argument:</p>
<pre><code>./prog input.txt &gt; output.txt
</code></pre>
<p>If original input file was small enough to fit in your terminal, you
can simply use <code>cat</code> to unscramble the output text.</p>
<pre><code>cat output.txt
</code></pre>
<p>It might seem like nothing was scrambled, but you can try passing the
output through <code>strings(1)</code> and see that most of the original strings
are gone. What happened is that the original text has been shuffled
with ANSI cursor positioning codes inserted such that characters are
printed in random order. This effect is more visible if there is a
delay after each character is printed. For convenience, an utility is
included in the source to output characters slowly:</p>
<pre><code>./prog input.txt | ruby prog.c
</code></pre>
<p>Scrambling order is deterministic, but you can reshuffle the output by
piping it through the same utility again, by specifying <code>-</code> as the
first argument:</p>
<pre><code>./prog input.txt | ./prog - | ./prog - | ...
</code></pre>
<p>You can also split the input to multiple files, each getting a subset
of the original input characters:</p>
<pre><code>./prog input.txt output1.txt output2.txt ...
cat output1.txt output2.txt ... &gt; unscrambled.txt
</code></pre>
<p>You can only unscramble files with <code>cat</code> if the input fits in a single
terminal screen. If you don&rsquo;t know what will be the terminal size of
the recipient, note that <code>prog.c</code> will fit in a 80x25 terminal, so a
good guideline is to pick files that have fewer rows and columns than
<code>prog.c</code>.</p>
<p>For files that are larger than your terminal window, <code>cat</code> will not be
sufficient for unscrambling because any scrolling causes the character
positions to be misaligned. But fear not, this utility also includes
unscrambling functionality. If no argument is specified, input will
be read through stdin and unscrambled to stdout:</p>
<pre><code>./prog &lt; scrambled.txt &gt; unscrambled.txt
</code></pre>
<p>Where this is useful is that if you scramble the input to multiple
files and unscramble each output files individually, those output
files can be printed on transparencies and distributed separately.</p>
<pre><code>./prog input.txt output1.txt output2.txt output3.txt
./prog &lt; output1.txt &gt; layer1.txt
./prog &lt; output2.txt &gt; layer2.txt
./prog &lt; output3.txt &gt; layer3.txt
</code></pre>
<p>In other words, this is a utility for facilitating
<a href="https://en.wikipedia.org/wiki/Visual_cryptography">visual cryptography</a>.</p>
<p>This utility can also be used just for removing trailing whitespaces
and expanding tabs to 8 spaces.</p>
<pre><code>./prog input.txt | ./prog
</code></pre>
<h1>Features</h1>
<h2>UTF-8 support</h2>
<p>A simple text scrambling utility might not have required a screenful
of code, but this particular one natively supports UTF-8.
Specifically: individual UTF-8 byte sequences will not be split into
broken ones, and the utility is aware of full-width versus half-width
differences such that cursor is positioned correctly for most CJK
input. <code>sample_input.txt</code> demonstrates this feature with a mix of
Basic Latin and Japanese characters.</p>
<p>Output cursor positions will most definitely be wrong for inputs
containing combining characters and right-to-left text, but it should
be possible to unscramble those text back to the original using this
same utility, since the utility is self-consistent in how cursor
positions are handled.</p>
<h2>Error handling</h2>
<p>If any file can not be opened for reading or writing, an error is
printed to stderr, and the utility will exit with nonzero status.</p>
<p>If there isn&rsquo;t enough memory, the utility will likely crash.</p>
<p>If input contains CR-LF end of line sequences, those CRs are silently
dropped. In fact, most control codes are silently ignored except line
feeds (preserved) and tabs (expanded to 8 spaces).</p>
<h2>Compatibility</h2>
<p>Verified to work and compiles without warnings on these environments:</p>
<ul>
<li> gcc 7.3.0 on Linux</li>
<li> gcc 7.4.0 on Cygwin</li>
<li> clang 4.0.1-10 on Linux</li>
<li> clang 5.0.1 on Cygwin</li>
<li> gcc 4.8.4 on Linux</li>
</ul>
<h2>Full version</h2>
<p>I tried really hard to make <code>prog.c</code> fit in a 80x25 terminal without
wrapping. If I were not constrained by space, I would have made an
ASCII art out of it. <code>violet.c</code> is that program, and also comes with
the minor benefit of supporting lines longer than a million columns
depending on <code>sizeof(int)</code>.</p>
<p>Violet is named after &ldquo;Violet Evergarden&rdquo;, the character who is highly
skilled in writing letters.</p>
<hr />
<TABLE><TR>
<TD><a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="/png/by-sa-3.0-88x31.png" /></a></TD>
<TD><P>&copy; Copyright 1984-2019,
<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="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
<TD>&nbsp;<!--<a href="https://validator.w3.org/check?uri=referer"><img src="https://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
</TR></TABLE>
</body>
</html>