force use of pandoc version >= 3.1.12.2

The `bin/pandoc-wrapper.sh` tool will verify that the ssytem
has a recent enough version of `pandoc(1)`.

We explain why we insist on `pandoc(1)`. version >= 3.1.12.2
in comments where the $PANDOC_MIN_VERSION is set.

Added `--wrap=preserve` as a default argument to `pandoc(1)`.
While this change will impact every HTML file generated,
we believe this will improve the ability of someone to look
at the generated HTML and correlate with the original markdown.

Changed `bin/pandoc-wrapper.sh` VERSION from "1.4.2 2024-03-17"
to "1.4.3 2024-03-18".

Performed `make www` to achieve all of the above and to generate
HTML using the new  `--wrap=preserve` `pandoc(1)` mode.
This commit is contained in:
Landon Curt Noll committed 2024-03-18 01:26:39 -07:00
1 parent 9eb7a54e9f
commit b0b212acb1
402 files changed
+37061 -55132

No files matched your search

+165 -255
View File
@@ -129,9 +129,9 @@
<h2 id="author"><a name="author"></a>Author:</h2>
<ul>
<li>Name: <a href="../../authors.html#Ondrej_Adamovsky">Ondřej
Adamovský</a><br> Location: <a href="../../location.html#CZ">CZ</a> -
<em>Czech Republic</em> (<em>Czechia</em>) <br><br></li>
<li>Name: <a href="../../authors.html#Ondrej_Adamovsky">Ondřej Adamovský</a><br>
Location: <a href="../../location.html#CZ">CZ</a> - <em>Czech Republic</em> (<em>Czechia</em>)
<br><br></li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-author.sh -->
@@ -144,8 +144,7 @@ Adamovský</a><br> Location: <a href="../../location.html#CZ">CZ</a> -
<h3 id="bugs-and-misfeatures">Bugs and (Mis)features:</h3>
<p>The current status of this entry is:</p>
<pre><code>STATUS: INABIAF - please **DO NOT** fix</code></pre>
<p>For more detailed information see <a
href="../../bugs.html#2019_adamovsky">2019 adamovsky bugs</a>.</p>
<p>For more detailed information see <a href="../../bugs.html#2019_adamovsky">2019 adamovsky bugs</a>.</p>
<h2 id="to-use">To use:</h2>
<div class="sourceCode" id="cb3"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> file.unl</span></code></pre></div>
<h2 id="try">Try:</h2>
@@ -153,107 +152,71 @@ href="../../bugs.html#2019_adamovsky">2019 adamovsky bugs</a>.</p>
<h2 id="judges-remarks">Judges’ remarks:</h2>
<p>Even after pre-processing and indenting, the C code of this entry it
is about as understandable as the Unlambda code.</p>
<p>Pretending that we don’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>
<p>Pretending that we don’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>
<p>Functional programming is not a panacea against core dumps, after all.</p>
<p>This can be demonstrated by:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> crash.unl</span></code></pre></div>
<h2 id="authors-remarks">Author’s remarks:</h2>
<h3 id="a-highly-structured-state-state-machine">A highly structured
state state machine</h3>
<h3 id="a-highly-structured-state-state-machine">A highly structured state state machine</h3>
<h3 id="purpose">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>
<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 id="aesthetics">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 which you should disregard its shape,
unless you like it, and the rest, which 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>λ</strong> character.</p>
<p>It might be a surprise for you that according to the IOCCC size tool
the program is actually a <code>one-liner</code>. 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>
<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
which you should disregard its shape, unless you like it, and the rest, which 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>λ</strong> character.</p>
<p>It might be a surprise for you that according to the IOCCC size tool the program is
actually a <code>one-liner</code>. 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 id="usage">Usage:</h3>
<p>When built directly using</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span></span></code></pre></div>
<p>the program (<code>prog</code>) 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 <a
href="advent.unl">advent.unl</a> file) and run it like this:</p>
<p>the program (<code>prog</code>) 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 <a href="advent.unl">advent.unl</a> file)
and run it like this:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> advent.unl</span></code></pre></div>
<blockquote>
<p>NOTE: the file was added to the entry so there is no need to download
it.</p>
<p>NOTE: the file was added to the entry so there is no need to download it.</p>
</blockquote>
<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 the 2018 IOCCC size
tool to complete. Put the tool source <a
href="iocccsize_2018.c">iocccsize_2018.c</a> in the project directory
and call</p>
<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 the 2018 IOCCC size tool to complete. Put the tool
source <a href="iocccsize_2018.c">iocccsize_2018.c</a> in the project directory and call</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span> identify</span></code></pre></div>
<p>It will build the tool and use it to build an alternative program
<code>prog2</code>, which in turn will produce an Unlambda program
<code>identify.unl</code>. <code>make identify</code> runs this program
to identify itself.</p>
<p>The base program (<code>prog</code>) implements an interpreter of
Unlambda 2.0. It recognises all its builtins (<code>k</code>,
<code>s</code>, <code>i</code>, <code>v</code>, <code>c</code>,
<code>d</code>, <code>.x</code>, <code>e</code>, <code>@</code>,
<code>?x</code> and <code>|</code>) including the syntactic sugar
function <code>r</code> and formatting properties in the form of
ignoring whitespace and comments to the end of line introduced by the
<code>#</code> character.</p>
<p>In case of wrong usage (missing Unlambda program file or missing
parameter) or use of an unseekable (<code>fseek(3)</code>) Unlambda
program source if it uses the <code>c</code> function, the program
returns the message <code>fail</code>. 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>
<p>It will build the tool and use it to build an alternative program <code>prog2</code>, which in turn will
produce an Unlambda program <code>identify.unl</code>. <code>make identify</code> runs this program to identify
itself.</p>
<p>The base program (<code>prog</code>) implements an interpreter of Unlambda 2.0. It
recognises all its builtins (<code>k</code>, <code>s</code>, <code>i</code>, <code>v</code>, <code>c</code>, <code>d</code>, <code>.x</code>, <code>e</code>, <code>@</code>, <code>?x</code>
and <code>|</code>) including the syntactic sugar function <code>r</code> and formatting properties in
the form of ignoring whitespace and comments to the end of line introduced by
the <code>#</code> character.</p>
<p>In case of wrong usage (missing Unlambda program file or missing parameter) or
use of an unseekable (<code>fseek(3)</code>) Unlambda program source if it uses the <code>c</code>
function, the program returns the message <code>fail</code>. 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 id="unlambda">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 in depth
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 the example programs provided or
try your wits in writing your own.</p>
<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 in depth 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 the example programs provided or try your wits in writing your own.</p>
<h3 id="hints">Hints:</h3>
<p>Here are some pointers where to start when trying to understand the
interpreter:</p>
<p>Here are some pointers where to start when trying to understand the interpreter:</p>
<ul>
<li>Where are syntax errors detected?</li>
<li>How is the memory managed?</li>
@@ -264,198 +227,145 @@ interpreter:</p>
</ul>
<h3 id="obfuscation-sources">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 <code>d</code> and the call with
current continuation <code>c</code>.</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 the
Unlambda functions are implemented.</li>
<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 <code>d</code>
and the call with current continuation <code>c</code>.</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 the Unlambda functions are
implemented.</li>
</ul>
<p>More on this in the <strong>Spoilers</strong> section.</p>
<h3 id="build-notes">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>clang -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>
<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>clang -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 id="portability">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>
<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. <code>trivial.unl</code> 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 <code>union</code>) had
much more members originally. I joined all integers to a single
<code>long long</code> member in the name of obfuscation. It is used for
reference counting (only 1 for every reference) among other uses.
<code>size_t</code> 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 <code>size_t</code> is bigger than
<code>long long</code>. It is also used for storing <code>char</code>s
for later printing. This might produce some warnings, but since it was
developed using <code>char</code>s it should be always used safely.</li>
<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.
<code>trivial.unl</code> 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 <code>union</code>) had much more
members originally. I joined all integers to a single <code>long long</code> member in the
name of obfuscation. It is used for reference counting (only 1 for every
reference) among other uses. <code>size_t</code> 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 <code>size_t</code> is bigger than <code>long long</code>. It is also used
for storing <code>char</code>s for later printing. This might produce some warnings, but
since it was developed using <code>char</code>s it should be always used safely.</li>
</ul>
<h3 id="spoilers">Spoilers:</h3>
<ul>
<li><p>You can examine the <a href="progSpoiler.c">progSpoiler.c</a>
file. It is the original final version of the interpreter, before I
started the downsizing. It accepts one more optional parameter that
specifies a filename for the output Unlambda function (it’s the Unlambda
function that remains after all function applications are done). When no
filename is provided, <code>stderr</code> 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 <code>T</code>.</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 a series
of applications and/or evaluations each of which may be a call to
current continuation), the <code>s</code> combinator and the
<code>`</code> 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
<code>r</code> instead of <code>f</code>)</p></li>
<li><p>The <code>`</code> 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 <code>T</code>, changing its function to build an
unevaluated sub-tree that is later evaluated whenever the promise is
<li><p>You can examine the <a href="progSpoiler.c">progSpoiler.c</a> file. It is the original
final version of the interpreter, before I started the downsizing. It accepts
one more optional parameter that specifies a filename for the output Unlambda
function (it’s the Unlambda function that remains after all function
applications are done). When no filename is provided, <code>stderr</code> 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
<code>T</code>.</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 a series of applications
and/or evaluations each of which may be a call to current continuation), the <code>s</code>
combinator and the <code>`</code> 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 <code>r</code> instead of <code>f</code>)</p></li>
<li><p>The <code>`</code> 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 <code>T</code>, changing its function
to build an unevaluated sub-tree 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 <code>Y</code> to possibly confuse with
<code>Y</code> 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
<code>S</code> and Apply functions were shuffled both for <code>S</code>
functions and Apply functions in the same way to hide the meaning of
<code>f</code> and <code>r</code> prefixes.</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 <code>Y</code> to possibly confuse with <code>Y</code> 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 <code>S</code> and Apply functions
were shuffled both for <code>S</code> functions and Apply functions in the same way to hide
the meaning of <code>f</code> and <code>r</code> prefixes.</p></li>
</ul>
<h3 id="identification-spoiler">Identification spoiler:</h3>
<p>The alternative build path <code>make identify</code> output
commemorates a <a href="../../2014/birken/index.html"
title="Best use of port 1701">previous IOCCC winning entry</a> which
uses similar methods to mess with the size tool.</p>
<p>The alternative build path <code>make identify</code> output commemorates a <a href="../../2014/birken/index.html" title="Best use of port 1701">previous IOCCC
winning entry</a> which uses similar methods to mess with the size tool.</p>
<h3 id="judges-spoilers">Judges’ 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 to not know what they are doing, created a
program that grows Unlambda execution stack indefinitely. You may
consider it an Unlambda anti-pattern. 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 be able to be
applied.</p>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0
License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights
Reserved. You are free to share and adapt this file under the terms of
this license:</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 to not know what they are doing, created a program that
grows Unlambda execution stack indefinitely. You may consider it an Unlambda
anti-pattern. 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 be able to
be applied.</p>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0 License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved.
You are free to share and adapt this file under the terms of this license:</p>
<pre><code>Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)</code></pre>
<p>For more information, see:
https://creativecommons.org/licenses/by-sa/4.0/</p>
<p>For more information, see: https://creativecommons.org/licenses/by-sa/4.0/</p>
<!-- END: this line ends content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
<!-- START: this line starts content for HTML phase 22 by: bin/output-index-inventory.sh via bin/md2html.sh -->
<!-- START: this line starts content generated by: bin/output-index-inventory.sh -->
<h1 id="inventory-for-2019adamovsky"><a name="inventory"></a>Inventory
for 2019/adamovsky</h1>
<h1 id="inventory-for-2019adamovsky"><a name="inventory"></a>Inventory for 2019/adamovsky</h1>
<p><a href="#top">Jump to top</a></p>
<h2 id="primary-files">Primary files</h2>
<ul>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/adamovsky/prog.c">prog.c</a>
- entry source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/adamovsky/Makefile">Makefile</a>
- entry Makefile</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/adamovsky/prog.orig.c">prog.orig.c</a>
- original source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/adamovsky/try.sh">try.sh</a>
- how to run</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/adamovsky/advent.unl">advent.unl</a>
- unlambda script</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/adamovsky/crash.unl">crash.unl</a>
- unlambda script</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/adamovsky/iocccsize_2018.c">iocccsize_2018.c</a>
- 2018 iocccsize source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/adamovsky/progSpoiler.c">progSpoiler.c</a>
- SPOILER WARNING</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/adamovsky/sierpinski.unl">sierpinski.unl</a>
- unlambda code</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/adamovsky/spam.unl">spam.unl</a>
- unlambda code</li>
<li><a href="2019_adamovsky.tar.bz2">2019_adamovsky.tar.bz2</a> -
download entry source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/adamovsky/prog.c">prog.c</a> - entry source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/adamovsky/Makefile">Makefile</a> - entry Makefile</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/adamovsky/prog.orig.c">prog.orig.c</a> - original source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/adamovsky/try.sh">try.sh</a> - how to run</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/adamovsky/advent.unl">advent.unl</a> - unlambda script</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/adamovsky/crash.unl">crash.unl</a> - unlambda script</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/adamovsky/iocccsize_2018.c">iocccsize_2018.c</a> - 2018 iocccsize source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/adamovsky/progSpoiler.c">progSpoiler.c</a> - SPOILER WARNING</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/adamovsky/sierpinski.unl">sierpinski.unl</a> - unlambda code</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/adamovsky/spam.unl">spam.unl</a> - unlambda code</li>
<li><a href="2019_adamovsky.tar.bz2">2019_adamovsky.tar.bz2</a> - download entry source</li>
</ul>
<h2 id="secondary-files">Secondary files</h2>
<ul>
<li><a href="index.html">index.html</a> - entry home page</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/adamovsky/.entry.json">.entry.json</a>
- description of entry in JSON</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/adamovsky/.gitignore">.gitignore</a>
- list of files that should not be committed under git</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/adamovsky/.entry.json">.entry.json</a> - description of entry in JSON</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/adamovsky/.gitignore">.gitignore</a> - list of files that should not be committed under git</li>
<li><a href=".path">.path</a> - directory path from top directory</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/adamovsky/README.md">README.md</a>
- markdown source for index.html</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/adamovsky/README.md">README.md</a> - markdown source for index.html</li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-inventory.sh -->
+48 -81
View File
@@ -130,8 +130,8 @@
<h2 id="author"><a name="author"></a>Author:</h2>
<ul>
<li>Name: <a href="../../authors.html#Dave_Burton">Dave Burton</a><br>
Location: <a href="../../location.html#US">US</a> - <em>United States of
America</em> (<em>United States</em>) <br><br></li>
Location: <a href="../../location.html#US">US</a> - <em>United States of America</em> (<em>United States</em>)
<br><br></li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-author.sh -->
@@ -144,8 +144,7 @@ America</em> (<em>United States</em>) <br><br></li>
<h3 id="bugs-and-misfeatures">Bugs and (Mis)features:</h3>
<p>The current status of this entry is:</p>
<pre><code>STATUS: INABIAF - please **DO NOT** fix</code></pre>
<p>For more detailed information see <a
href="../../bugs.html#2019_burton">2019 burton bugs</a>.</p>
<p>For more detailed information see <a href="../../bugs.html#2019_burton">2019 burton bugs</a>.</p>
<h2 id="to-use">To use:</h2>
<div class="sourceCode" id="cb3"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> <span class="op">&lt;</span> file</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a></span>
@@ -153,112 +152,80 @@ href="../../bugs.html#2019_burton">2019 burton bugs</a>.</p>
<h2 id="try">Try:</h2>
<div class="sourceCode" id="cb4"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./try.sh</span></span></code></pre></div>
<h2 id="judges-remarks">Judges’ remarks:</h2>
<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>
<p>You might find the author’s <a href="on.one.liners.txt">commentary on
one liners</a> interesting.</p>
<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>
<p>You might find the author’s <a href="on.one.liners.txt">commentary on one liners</a>
interesting.</p>
<h2 id="authors-remarks">Author’s remarks:</h2>
<h3 id="synopsis">Synopsis:</h3>
<p>Feed it anything on <code>stdin</code>. The output should look
familiar.</p>
<p>Feed it anything on <code>stdin</code>.
The output should look familiar.</p>
<p>Compiles cleanly with:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="va">WARN</span><span class="op">=</span><span class="st">&quot;-Wno-implicit-int -Wno-missing-variable-declarations -Wno-parentheses&quot;</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="fu">cc</span> <span class="at">-Wall</span> <span class="at">-Wextra</span> <span class="at">-Weverything</span> <span class="at">-pedantic</span> <span class="va">$WARN</span> <span class="at">-include</span> stdio.h <span class="at">-o</span> prog prog.c</span></code></pre></div>
<h3 id="description">Description:</h3>
<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 <a
href="check.sh">check.sh</a> script can simply output the results: (The
Makefile contains the spoiler):</p>
<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 <a href="check.sh">check.sh</a> script can simply output the
results: (The Makefile contains the spoiler):</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="va">out</span><span class="op">=</span>cat <span class="ex">./check.sh</span> ./prog</span></code></pre></div>
<p>Interestingly, and a spoiler here: macOS and FreeBSD implement the
common utility “correctly”. CentOS and Ubuntu both share a “flawed”
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: <code>\a</code> and <code>\b</code> 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>
<p>Interestingly, and a spoiler here: macOS and FreeBSD implement the common
utility “correctly”. CentOS and Ubuntu both share a “flawed” 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:
<code>\a</code> and <code>\b</code> 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>
<h3 id="limits">Limits:</h3>
<p>Requires the C locale and ASCII character set. Input should be less
than ten million octets “toavoidthisproblem”.</p>
<p>Requires the C locale and ASCII character set.
Input should be less than ten million octets “toavoidthisproblem”.</p>
<h3 id="see-also">See Also:</h3>
<p>You can enjoy this code from beginning to end. No whitespace was
harmed in the creation of this program. All your base belong to us, but
the constants seem a bit … off?</p>
<p>You can enjoy this code from beginning to end.
No whitespace was harmed in the creation of this program.
All your base belong to us, but the constants seem a bit … off?</p>
<h3 id="bonus">Bonus</h3>
<p>The script <a href="cow.sh">cow.sh</a> provides a closer analog, and
perhaps a more useful interface.</p>
<p>The script <a href="cow.sh">cow.sh</a> provides a closer analog, and perhaps a more useful
interface.</p>
<p>Included is a version without compilation warnings:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="fu">cc</span> <span class="at">-Wall</span> <span class="at">-Wextra</span> <span class="at">-Weverything</span> <span class="at">-pedantic</span> <span class="at">-include</span> stdio.h <span class="at">-o</span> prog.clean prog.clean.c</span></code></pre></div>
<h3 id="bugs">Bugs</h3>
<p>The flags are not supported. Although they could easily be added into
<code>cow.sh</code>. This exercise left to the reader.</p>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0
License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights
Reserved. You are free to share and adapt this file under the terms of
this license:</p>
<p>The flags are not supported. Although they could easily be added into <code>cow.sh</code>.
This exercise left to the reader.</p>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0 License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved.
You are free to share and adapt this file under the terms of this license:</p>
<pre><code>Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)</code></pre>
<p>For more information, see:
https://creativecommons.org/licenses/by-sa/4.0/</p>
<p>For more information, see: https://creativecommons.org/licenses/by-sa/4.0/</p>
<!-- END: this line ends content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
<!-- START: this line starts content for HTML phase 22 by: bin/output-index-inventory.sh via bin/md2html.sh -->
<!-- START: this line starts content generated by: bin/output-index-inventory.sh -->
<h1 id="inventory-for-2019burton"><a name="inventory"></a>Inventory for
2019/burton</h1>
<h1 id="inventory-for-2019burton"><a name="inventory"></a>Inventory for 2019/burton</h1>
<p><a href="#top">Jump to top</a></p>
<h2 id="primary-files">Primary files</h2>
<ul>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/burton/prog.c">prog.c</a>
- entry source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/burton/Makefile">Makefile</a>
- entry Makefile</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/burton/prog.orig.c">prog.orig.c</a>
- original source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/burton/check.sh">check.sh</a>
- test suite</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/burton/cow.sh">cow.sh</a>
- an alternate implementation with a useful interface</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/burton/on.one.liners.txt">on.one.liners.txt</a>
- on writing an IOCCC one-liner</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/burton/try.sh">try.sh</a>
- how to run</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/burton/prog.clean.c">prog.clean.c</a>
- version of source without compilation warnings</li>
<li><a href="2019_burton.tar.bz2">2019_burton.tar.bz2</a> - download
entry source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/burton/prog.c">prog.c</a> - entry source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/burton/Makefile">Makefile</a> - entry Makefile</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/burton/prog.orig.c">prog.orig.c</a> - original source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/burton/check.sh">check.sh</a> - test suite</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/burton/cow.sh">cow.sh</a> - an alternate implementation with a useful interface</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/burton/on.one.liners.txt">on.one.liners.txt</a> - on writing an IOCCC one-liner</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/burton/try.sh">try.sh</a> - how to run</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/burton/prog.clean.c">prog.clean.c</a> - version of source without compilation warnings</li>
<li><a href="2019_burton.tar.bz2">2019_burton.tar.bz2</a> - download entry source</li>
</ul>
<h2 id="secondary-files">Secondary files</h2>
<ul>
<li><a href="index.html">index.html</a> - entry home page</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/burton/.entry.json">.entry.json</a>
- description of entry in JSON</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/burton/.gitignore">.gitignore</a>
- list of files that should not be committed under git</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/burton/.entry.json">.entry.json</a> - description of entry in JSON</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/burton/.gitignore">.gitignore</a> - list of files that should not be committed under git</li>
<li><a href=".path">.path</a> - directory path from top directory</li>
<li><a href="256">256</a> - test suite data</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/burton/README.md">README.md</a>
- markdown source for index.html</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/burton/newlines">newlines</a>
- more useful interface.</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/burton/README.md">README.md</a> - markdown source for index.html</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/burton/newlines">newlines</a> - more useful interface.</li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-inventory.sh -->
+100 -168
View File
@@ -130,8 +130,8 @@
<h2 id="author"><a name="author"></a>Author:</h2>
<ul>
<li>Name: <a href="../../authors.html#Marcin_Ciura">Marcin Ciura</a><br>
Location: <a href="../../location.html#PL">PL</a> - <em>Republic of
Poland</em> (<em>Poland</em>) <br><br></li>
Location: <a href="../../location.html#PL">PL</a> - <em>Republic of Poland</em> (<em>Poland</em>)
<br><br></li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-author.sh -->
@@ -141,21 +141,19 @@ Poland</em> (<em>Poland</em>) <br><br></li>
<h2 id="to-build">To build:</h2>
<div class="sourceCode" id="cb1"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span></span></code></pre></div>
<p>There is an alternate version available. See <a
href="#alternate-code">Alternate code</a> below.</p>
<p>There is an alternate version available. See <a href="#alternate-code">Alternate code</a>
below.</p>
<h3 id="bugs-and-misfeatures">Bugs and (Mis)features:</h3>
<p>The current status of this entry is:</p>
<pre><code>STATUS: INABIAF - please **DO NOT** fix</code></pre>
<p>For more detailed information see <a
href="../../bugs.html#2019_ciura">2019 ciura bugs</a>.</p>
<p>For more detailed information see <a href="../../bugs.html#2019_ciura">2019 ciura bugs</a>.</p>
<h2 id="to-use">To use:</h2>
<div class="sourceCode" id="cb3"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./getwords.sh</span> en <span class="kw">|</span> <span class="fu">grep</span> .. <span class="kw">|</span> <span class="ex">./prog</span> string</span></code></pre></div>
<h2 id="try">Try:</h2>
<div class="sourceCode" id="cb4"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./try.sh</span></span></code></pre></div>
<h2 id="alternate-code">Alternate code:</h2>
<p>There is an alternate version of this code that flushes
<code>stdout</code> after writing a newline. See the Author’s remarks
for more information.</p>
<p>There is an alternate version of this code that flushes <code>stdout</code> after writing a
newline. See the Author’s remarks for more information.</p>
<h3 id="alternate-build">Alternate build:</h3>
<div class="sourceCode" id="cb5"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span> alt</span></code></pre></div>
<h3 id="alternate-use">Alternate use:</h3>
@@ -163,13 +161,13 @@ for more information.</p>
<h3 id="alternate-try">Alternate try:</h3>
<div class="sourceCode" id="cb6"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./try.alt.sh</span></span></code></pre></div>
<h2 id="judges-remarks">Judges’ remarks:</h2>
<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 remove all of the
goto jumps in this code?</p>
<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 remove all of the goto jumps in
this code?</p>
<h2 id="authors-remarks">Author’s remarks:</h2>
<h3 id="what-is-this">What is this? <a name="wit"></a></h3>
<p>This entry reads from standard input a list of words in any language
@@ -196,191 +194,125 @@ of the alphabet exactly once.</p>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true" tabindex="-1"></a><span class="ex">quiz</span> jamb pyx vs kc growl fed nth</span></code></pre></div>
<p>Rearranging the words into more or less meaningful expressions is the
user’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’s
website</a>, converted to PDF as <a href="fasc5c.pdf">fasc5c.pdf</a> for
your convenience.</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’s
website</a>, converted to
PDF as <a href="fasc5c.pdf">fasc5c.pdf</a> for your convenience.</p>
<h3 id="usage">Usage:</h3>
<p><code>./prog LETTERS [N]</code></p>
<p>reads allowed words from standard input and writes perfect pangrams
with at most <code>N</code> words composed of <code>LETTERS</code> to
standard output, one per line. If <code>N</code> is not given, the
number of words in the pangrams is unlimited. The characters in
<code>LETTERS</code> must not repeat. The length of <code>LETTERS</code>
must not exceed 97 characters.</p>
with at most <code>N</code> words composed of <code>LETTERS</code> to standard output, one
per line. If <code>N</code> is not given, the number of words in the pangrams is
unlimited. The characters in <code>LETTERS</code> must not repeat. The length of
<code>LETTERS</code> 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 id="helper-scripts">Helper scripts:</h3>
<ul>
<li><p><a href="getwords.sh">getwords.sh</a></p>
<p><code>./getwords.sh LANGUAGE_CODE</code></p>
<p>outputs a sorted list of unique words in a given language, one per
line. It requires <code>aspell</code> with a dictionary for
<em>LANGUAGE_CODE</em>.</p></li>
<p>outputs a sorted list of unique words in a given language, one per line. It
requires <code>aspell</code> with a dictionary for <em>LANGUAGE_CODE</em>.</p></li>
<li><p><a href="wrapprog.py">wrapprog.py</a></p>
<p><code>./wrapprog.py LETTERS [N]</code></p>
<p>works similarly to <code>./prog LETTERS [N]</code> except that it
merges pangrams before passing them to <code>prog</code> and expands
them in <code>prog</code>’s output. This way, it finishes the job faster
than <code>prog</code> when there are millions of perfect pangrams. It
requires a UTF-8 locale.</p></li>
<li><p><a href="de.sh">de.sh</a>, <a href="en.sh">en.sh</a>, <a
href="fr.sh">fr.sh</a>, <a href="it.sh">it.sh</a>, <a
href="pl.sh">pl.sh</a>, and <a href="ru.sh">ru.sh</a> output German,
English, French, Italian, Polish, and Russian perfect pangrams,
respectively. They require a UTF-8 locale.</p></li>
<p>works similarly to <code>./prog LETTERS [N]</code> except that it merges pangrams
before passing them to <code>prog</code> and expands them in <code>prog</code>’s output. This way,
it finishes the job faster than <code>prog</code> when there are millions of perfect
pangrams. It requires a UTF-8 locale.</p></li>
<li><p><a href="de.sh">de.sh</a>, <a href="en.sh">en.sh</a>, <a href="fr.sh">fr.sh</a>, <a href="it.sh">it.sh</a>,
<a href="pl.sh">pl.sh</a>, and <a href="ru.sh">ru.sh</a> output German,
English, French, Italian, Polish, and Russian perfect pangrams, respectively.
They require a UTF-8 locale.</p></li>
</ul>
<h3 id="miscellaneous-remarks">Miscellaneous remarks:</h3>
<p>I dare submit this entry to categories <em>algorithms</em>,
<em>internationalization</em> (I have not found active use of
<code>&lt;wchar.h&gt;</code> 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="../../2005/klausler/index.html">2005/klausler</a>. However,
<code>prog</code> is internationalized and way faster. On my machine,
<code>./klausler abcdefghijklmnopqrstuvwxyz</code> printed only 3,965
perfect pangrams until I killed it after 144 hours running, while the
<em>internationalization</em> (I have not found active use of <code>&lt;wchar.h&gt;</code>
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="../../2005/klausler/index.html">2005/klausler</a>.
However, <code>prog</code> is internationalized and way faster. On my machine,
<code>./klausler abcdefghijklmnopqrstuvwxyz</code> printed only 3,965 perfect
pangrams until I killed it after 144 hours running, while the
equivalent
<code>tr A-Z a-z &lt; /usr/share/dict/words | egrep -v '^[^ais]$' | ./prog abcdefghijklmnopqrstuvwxyz | wc -l</code>
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, <code>prog</code> can only output
series of words with non-repeating characters, unlike
<code>klausler</code>.</p>
<p>In contrast to <a href="prog.alt.c">prog.alt.c</a>, <a
href="prog.c">prog.c</a> does not call <code>fflush(stdout)</code> after
outputting each line, thus running faster. I am grateful to Witold
Jarnicki for suggesting this change. The original <code>prog</code>
finished the example above in 100 minutes instead of 62 minutes.</p>
the example from section <a href="#wit">What is this?</a> finished in 1.35
seconds. On the other hand, <code>prog</code> can only output series of words
with non-repeating characters, unlike <code>klausler</code>.</p>
<p>In contrast to <a href="prog.alt.c">prog.alt.c</a>, <a href="prog.c">prog.c</a> does not call
<code>fflush(stdout)</code> after outputting each line, thus running faster.
I am grateful to Witold Jarnicki for suggesting this change.
The original <code>prog</code> finished the example above in 100 minutes
instead of 62 minutes.</p>
<p>If your word list contains meaningless one-letter words, pipe
<code>grep .. [FILE]</code> through <code>prog</code> to eliminate the
pangrams that contain them.</p>
<p>According to <code>prog</code> and <code>aspell</code>, some
languages, e.g. Spanish, have no perfect pangrams.</p>
<p>Why does <code>yes | ./prog y</code> hang on Linux? Change
<code>static int</code> to <code>int</code> and
<code>static wchar_t</code> to <code>wchar_t</code>, and recompile
<code>prog</code>. Why does <code>yes | ./prog y</code> dump core now?
Change the line <code>#define P 9&lt;&lt;23^1</code> to
<code>#define P 9&lt;&lt;23</code> and recompile <code>prog</code>. Why
does <code>yes | ./prog y</code> exit gracefully?</p>
<p>Answer: As of June 2019, thus manifest bugs in <code>glibc</code>
2.22–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 <code>goto</code> three times. While it could
easily get by without <code>goto M</code> and <code>goto H</code>, I
challenge the adherents of structured programming to refactor
<code>goto T</code>, which jumps back into a nested <code>if</code>
block.</p>
<p>With the supplied <a href="Makefile">Makefile</a>, both
<code>gcc</code> and <code>clang</code> compile <a
href="prog.c">prog.c</a> without warnings in C11 and C99 mode. For a
clean compilation with <code>gcc -std=c90</code>, add
<code>-Wno-format</code> to <code>CSILENCE</code> in
<code>Makefile</code>.</p>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0
License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights
Reserved. You are free to share and adapt this file under the terms of
this license:</p>
<code>grep .. [FILE]</code> through <code>prog</code> to eliminate the pangrams that
contain them.</p>
<p>According to <code>prog</code> and <code>aspell</code>, some languages, e.g. Spanish,
have no perfect pangrams.</p>
<p>Why does <code>yes | ./prog y</code> hang on Linux? Change <code>static int</code> to
<code>int</code> and <code>static wchar_t</code> to <code>wchar_t</code>, and recompile
<code>prog</code>. Why does <code>yes | ./prog y</code> dump core now? Change the line
<code>#define P 9&lt;&lt;23^1</code> to <code>#define P 9&lt;&lt;23</code> and recompile
<code>prog</code>. Why does <code>yes | ./prog y</code> exit gracefully?</p>
<p>Answer: As of June 2019, thus manifest bugs in <code>glibc</code> 2.22–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 <code>goto</code> three times. While it could easily get
by without <code>goto M</code> and <code>goto H</code>, I challenge the adherents of
structured programming to refactor <code>goto T</code>, which jumps back into a
nested <code>if</code> block.</p>
<p>With the supplied <a href="Makefile">Makefile</a>, both <code>gcc</code> and <code>clang</code> compile
<a href="prog.c">prog.c</a> without warnings in C11 and C99 mode. For a clean
compilation with <code>gcc -std=c90</code>, add <code>-Wno-format</code> to
<code>CSILENCE</code> in <code>Makefile</code>.</p>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0 License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved.
You are free to share and adapt this file under the terms of this license:</p>
<pre><code>Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)</code></pre>
<p>For more information, see:
https://creativecommons.org/licenses/by-sa/4.0/</p>
<p>For more information, see: https://creativecommons.org/licenses/by-sa/4.0/</p>
<!-- END: this line ends content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
<!-- START: this line starts content for HTML phase 22 by: bin/output-index-inventory.sh via bin/md2html.sh -->
<!-- START: this line starts content generated by: bin/output-index-inventory.sh -->
<h1 id="inventory-for-2019ciura"><a name="inventory"></a>Inventory for
2019/ciura</h1>
<h1 id="inventory-for-2019ciura"><a name="inventory"></a>Inventory for 2019/ciura</h1>
<p><a href="#top">Jump to top</a></p>
<h2 id="primary-files">Primary files</h2>
<ul>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/prog.c">prog.c</a>
- entry source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/Makefile">Makefile</a>
- entry Makefile</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/prog.alt.c">prog.alt.c</a>
- alternative source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/prog.orig.c">prog.orig.c</a>
- original source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/de.alt.sh">de.alt.sh</a>
- how to run alternative code in Germain</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/en.alt.sh">en.alt.sh</a>
- how to run alternative code in English</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/getwords.sh">getwords.sh</a>
- how to run</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/it.alt.sh">it.alt.sh</a>
- how to run alternative code in Italian</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/pl.alt.sh">pl.alt.sh</a>
- how to run alternative code in Polish</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/ru.alt.sh">ru.alt.sh</a>
- how to run alternative code in Russian</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/try.alt.sh">try.alt.sh</a>
- how to run alternative code</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/try.sh">try.sh</a>
- how to run</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/wrapprog.py">wrapprog.py</a>
- merge pangrams before passing them to prog</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/de.sh">de.sh</a>
- run with German data</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/en.sh">en.sh</a>
- run with English data</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/fr.alt.sh">fr.alt.sh</a>
- how to run alternative code in French</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/fr.sh">fr.sh</a>
- run with French data</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/it.sh">it.sh</a>
- run with Italian data</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/pl.sh">pl.sh</a>
- run with Polish data</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/ru.sh">ru.sh</a>
- run with Russian data</li>
<li><a href="fasc5c.pdf">fasc5c.pdf</a> - The Art of Computer
Programming vol 4 draft</li>
<li><a href="2019_ciura.tar.bz2">2019_ciura.tar.bz2</a> - download entry
source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/prog.c">prog.c</a> - entry source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/Makefile">Makefile</a> - entry Makefile</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/prog.alt.c">prog.alt.c</a> - alternative source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/prog.orig.c">prog.orig.c</a> - original source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/de.alt.sh">de.alt.sh</a> - how to run alternative code in Germain</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/en.alt.sh">en.alt.sh</a> - how to run alternative code in English</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/getwords.sh">getwords.sh</a> - how to run</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/it.alt.sh">it.alt.sh</a> - how to run alternative code in Italian</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/pl.alt.sh">pl.alt.sh</a> - how to run alternative code in Polish</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/ru.alt.sh">ru.alt.sh</a> - how to run alternative code in Russian</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/try.alt.sh">try.alt.sh</a> - how to run alternative code</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/try.sh">try.sh</a> - how to run</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/wrapprog.py">wrapprog.py</a> - merge pangrams before passing them to prog</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/de.sh">de.sh</a> - run with German data</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/en.sh">en.sh</a> - run with English data</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/fr.alt.sh">fr.alt.sh</a> - how to run alternative code in French</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/fr.sh">fr.sh</a> - run with French data</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/it.sh">it.sh</a> - run with Italian data</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/pl.sh">pl.sh</a> - run with Polish data</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/ru.sh">ru.sh</a> - run with Russian data</li>
<li><a href="fasc5c.pdf">fasc5c.pdf</a> - The Art of Computer Programming vol 4 draft</li>
<li><a href="2019_ciura.tar.bz2">2019_ciura.tar.bz2</a> - download entry source</li>
</ul>
<h2 id="secondary-files">Secondary files</h2>
<ul>
<li><a href="index.html">index.html</a> - entry home page</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/.entry.json">.entry.json</a>
- description of entry in JSON</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/.gitignore">.gitignore</a>
- list of files that should not be committed under git</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/.entry.json">.entry.json</a> - description of entry in JSON</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/.gitignore">.gitignore</a> - list of files that should not be committed under git</li>
<li><a href=".path">.path</a> - directory path from top directory</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/README.md">README.md</a>
- markdown source for index.html</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/ciura/README.md">README.md</a> - markdown source for index.html</li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-inventory.sh -->
+34 -62
View File
@@ -129,9 +129,9 @@
<h2 id="author"><a name="author"></a>Author:</h2>
<ul>
<li>Name: <a href="../../authors.html#Volker_Diels-Grabsch">Volker
Diels-Grabsch</a><br> Location: <a href="../../location.html#DE">DE</a>
- <em>Federal Republic of Germany</em> (<em>Germany</em>) <br><br></li>
<li>Name: <a href="../../authors.html#Volker_Diels-Grabsch">Volker Diels-Grabsch</a><br>
Location: <a href="../../location.html#DE">DE</a> - <em>Federal Republic of Germany</em> (<em>Germany</em>)
<br><br></li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-author.sh -->
@@ -146,14 +146,13 @@ Diels-Grabsch</a><br> Location: <a href="../../location.html#DE">DE</a>
<h2 id="try">Try:</h2>
<div class="sourceCode" id="cb3"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./try.sh</span></span></code></pre></div>
<h2 id="judges-remarks">Judges’ remarks:</h2>
<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 <code>/dev/zero</code> file compresses
identically by the entry and the standard <code>compress(1)</code> tool
(see <a href="try.sh">try.sh</a>), but the text file compresses
differently? The judges know. :)</p>
<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 <code>/dev/zero</code> file compresses identically by the entry and
the standard <code>compress(1)</code> tool (see <a href="try.sh">try.sh</a>), but the text file
compresses differently? The judges know. :)</p>
<h2 id="authors-remarks">Author’s remarks:</h2>
<h3 id="a-tiny-compress-tool">A tiny “compress” tool:</h3>
<h4 id="usage">Usage:</h4>
@@ -163,74 +162,47 @@ differently? The judges know. :)</p>
<h4 id="check-for-correctness">Check for correctness:</h4>
<div class="sourceCode" id="cb6"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="fu">zcat</span> guidelines.txt.Z <span class="op">&gt;</span> guidelines2.txt</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="fu">diff</span> <span class="at">-s</span> guidelines.txt guidelines2.txt</span></code></pre></div>
<p>Of course you can also use <a
href="../../2015/mills2/mills2.c">2015/mills2</a> instead of
<code>zcat</code> to verify the output file. The achieved compression
ratio roughly matches that of the classic Unix <code>compress(1)</code>
tool. And the source code is very compressed, too: It has exactly the
same size as the paragraph you are reading right now. And exactly the
same shape. Nevertheless, it is portable C99 code that runs on 32-bit
and 64-bit platforms. It compiles without warnings on both GCC and Clang
even with <code>-Wextra and -Weverything</code>.</p>
<p>Of course you can also use <a href="../../2015/mills2/mills2.c">2015/mills2</a> instead of
<code>zcat</code> to verify the output file. The achieved compression ratio roughly matches
that of the classic Unix <code>compress(1)</code> tool. And the source code is very
compressed, too: It has exactly the same size as the paragraph you are reading
right now. And exactly the same shape. Nevertheless, it is portable C99 code
that runs on 32-bit and 64-bit platforms. It compiles without warnings on both
GCC and Clang even with <code>-Wextra and -Weverything</code>.</p>
<blockquote>
<p>2023 note: the above paragraph might not be true as far as number of
bytes goes.</p>
<p>2023 note: the above paragraph might not be true as far as number of bytes
goes.</p>
</blockquote>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0
License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights
Reserved. You are free to share and adapt this file under the terms of
this license:</p>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0 License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved.
You are free to share and adapt this file under the terms of this license:</p>
<pre><code>Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)</code></pre>
<p>For more information, see:
https://creativecommons.org/licenses/by-sa/4.0/</p>
<p>For more information, see: https://creativecommons.org/licenses/by-sa/4.0/</p>
<!-- END: this line ends content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
<!-- START: this line starts content for HTML phase 22 by: bin/output-index-inventory.sh via bin/md2html.sh -->
<!-- START: this line starts content generated by: bin/output-index-inventory.sh -->
<h1
id="inventory-for-2019diels-grabsch1"><a name="inventory"></a>Inventory
for 2019/diels-grabsch1</h1>
<h1 id="inventory-for-2019diels-grabsch1"><a name="inventory"></a>Inventory for 2019/diels-grabsch1</h1>
<p><a href="#top">Jump to top</a></p>
<h2 id="primary-files">Primary files</h2>
<ul>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch1/prog.c">prog.c</a>
- entry source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch1/Makefile">Makefile</a>
- entry Makefile</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch1/prog.orig.c">prog.orig.c</a>
- original source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch1/guidelines.txt">guidelines.txt</a>
- input data from 2018 IOCCC guidelines</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch1/try.sh">try.sh</a>
- how to run</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch1/Shakespeare.txt">Shakespeare.txt</a>
- Coriolanus by Shakespeare</li>
<li><a
href="2019_diels-grabsch1.tar.bz2">2019_diels-grabsch1.tar.bz2</a> -
download entry source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch1/prog.c">prog.c</a> - entry source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch1/Makefile">Makefile</a> - entry Makefile</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch1/prog.orig.c">prog.orig.c</a> - original source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch1/guidelines.txt">guidelines.txt</a> - input data from 2018 IOCCC guidelines</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch1/try.sh">try.sh</a> - how to run</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch1/Shakespeare.txt">Shakespeare.txt</a> - Coriolanus by Shakespeare</li>
<li><a href="2019_diels-grabsch1.tar.bz2">2019_diels-grabsch1.tar.bz2</a> - download entry source</li>
</ul>
<h2 id="secondary-files">Secondary files</h2>
<ul>
<li><a href="index.html">index.html</a> - entry home page</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch1/.entry.json">.entry.json</a>
- description of entry in JSON</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch1/.gitignore">.gitignore</a>
- list of files that should not be committed under git</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch1/.entry.json">.entry.json</a> - description of entry in JSON</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch1/.gitignore">.gitignore</a> - list of files that should not be committed under git</li>
<li><a href=".path">.path</a> - directory path from top directory</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch1/README.md">README.md</a>
- markdown source for index.html</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch1/README.md">README.md</a> - markdown source for index.html</li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-inventory.sh -->
+98 -128
View File
@@ -129,9 +129,9 @@
<h2 id="author"><a name="author"></a>Author:</h2>
<ul>
<li>Name: <a href="../../authors.html#Volker_Diels-Grabsch">Volker
Diels-Grabsch</a><br> Location: <a href="../../location.html#DE">DE</a>
- <em>Federal Republic of Germany</em> (<em>Germany</em>) <br><br></li>
<li>Name: <a href="../../authors.html#Volker_Diels-Grabsch">Volker Diels-Grabsch</a><br>
Location: <a href="../../location.html#DE">DE</a> - <em>Federal Republic of Germany</em> (<em>Germany</em>)
<br><br></li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-author.sh -->
@@ -146,30 +146,27 @@ Diels-Grabsch</a><br> Location: <a href="../../location.html#DE">DE</a>
<h2 id="try">Try:</h2>
<div class="sourceCode" id="cb3"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./try.sh</span></span></code></pre></div>
<h2 id="judges-remarks">Judges’ remarks:</h2>
<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>
<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 id="authors-remarks">Author’s remarks:</h2>
<h3 id="almost-a-hash-collision">Almost a hash collision:</h3>
<p>This program prints its own SHA-512 hash. To verify, run:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> sha512sum prog.c<span class="kw">;</span> <span class="ex">./prog</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="ex">43bd0c4381a5078d2850fca9ae5e0647596bcc03cd67d8d973ad02ff35c316c728e7b347ca70abe6c74e745e63646cc7643cb0cffcd3d9a969cbf31a7ce5bf68</span> prog.c</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="ex">43bd0c4381a5078d2850fca9ae5e0647596bcc03cd67d8d973ad02ff35c316c728e7b347ca70abe6c74e745e63646cc7643cb0cffcd3d9a969cbf31a7ce5bf68</span></span></code></pre></div>
<p>It started as a complicated “hello world” program that prints some
random hex digits instead of “hello world”. Then, the digits were
adjusted until the resulting program matched its own SHA-512 hash, via
brute force through all 2^512 possibilities. Just kidding.</p>
<p>This wasn’t brute force, but involved quite some math, using a
variant of Jane Doe’s algorithm for generating SHA-512 collisions
efficiently. If you still don’t believe me, you are right.</p>
<p>It started as a complicated “hello world” program that prints some random hex
digits instead of “hello world”. Then, the digits were adjusted until the
resulting program matched its own SHA-512 hash, via brute force through all
2^512 possibilities. Just kidding.</p>
<p>This wasn’t brute force, but involved quite some math, using a variant of Jane
Doe’s algorithm for generating SHA-512 collisions efficiently. If you still
don’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 own source), its SHA-512 hash is computed
and printed. So two major steps were needed to obfuscate 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 own source), its SHA-512 hash is computed and printed. So two major
steps were needed to obfuscate this program:</p>
<ol type="1">
<li>Hide the quine.</li>
<li>Hide the SHA-512 computation.</li>
@@ -177,28 +174,26 @@ program:</p>
<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
<code>-Wextra -Weverything</code>. The program is composed of mostly
pure functions, and the <code>#define</code>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>
any warnings on current GCC and Clang versions even with <code>-Wextra -Weverything</code>. The program is composed of mostly pure functions, and
the <code>#define</code>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</p>
<pre><code>&quot;`x{bh}ndbq...&quot;</code></pre>
<p>in the last line doesn’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
<code>"</code> 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 <code>"</code>,
<code>;</code> and <code>\n</code>. Those 3 characters are short enough
to be hidden in … well, let’s leave this as an exercise for the
reader.</p>
subsequent code. Instead, the preceding code including the <code>"</code>
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 <code>"</code>, <code>;</code> and <code>\n</code>. Those 3
characters are short enough to be hidden in … well, let’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 pre-calculated and the subsequent
code is short enough to be hidden anywhere.</p>
@@ -206,134 +201,109 @@ code is short enough to be hidden anywhere.</p>
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
<code>0x428a2f98d728ae22</code>) would tell the reader immediately
what’s going on. Because of the pre-computation, the 8 initial hash
<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 <code>0x428a2f98d728ae22</code>) would tell the reader
immediately what’s going on. Because of the pre-computation, 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 constants 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
<code>pow(3)</code>, 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 <code>double</code> has
only 53-bit mantissa precision.</p>
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 constants 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 <code>pow(3)</code>, 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 <code>double</code> 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>
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’t need floating point and can use 64-bit integers instead.
But that still doesn’t solve the problem as it poses the following new
challenges:</p>
bisection, and calculates their cubes until those match the given
prime. Thus, we don’t need floating point and can use 64-bit integers
instead. But that still doesn’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 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’t standard and
wouldn’t have been portable C99.</p>
32-bit integers to get the 64-bit product at full precision. While
GCC and Clang both support 128-bit arithmetics, that isn’t standard
and wouldn’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>
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
<code>3*67=201</code> bits, but fortunately we only need to check if it
is close enough to the actual prime. It won’t be exactly
<code>409.0000...</code> 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>
<code>3*67=201</code> bits, but fortunately we only need to check if it is close
enough to the actual prime. It won’t be exactly <code>409.0000...</code>
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 “digits” of base <code>2^24</code> each. During that calculation,
24-bit each. Those are cubed using the multiplication formulas
numbers with 3 “digits” of base <code>2^24</code> 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 working 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
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’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
<code>if()</code>, where the final <code>"\";\n"</code> 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’s documented here is all you need to know to write
your own version of that program.</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 <code>if()</code>, where
the final <code>"\";\n"</code> 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’s
documented here is all you need to know to write your own version of
that program.</p>
<p>I’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
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 was unable to make it work with 2 parts, but that
doesn’t have to mean anything.</p>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0
License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights
Reserved. You are free to share and adapt this file under the terms of
this license:</p>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0 License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved.
You are free to share and adapt this file under the terms of this license:</p>
<pre><code>Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)</code></pre>
<p>For more information, see:
https://creativecommons.org/licenses/by-sa/4.0/</p>
<p>For more information, see: https://creativecommons.org/licenses/by-sa/4.0/</p>
<!-- END: this line ends content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
<!-- START: this line starts content for HTML phase 22 by: bin/output-index-inventory.sh via bin/md2html.sh -->
<!-- START: this line starts content generated by: bin/output-index-inventory.sh -->
<h1
id="inventory-for-2019diels-grabsch2"><a name="inventory"></a>Inventory
for 2019/diels-grabsch2</h1>
<h1 id="inventory-for-2019diels-grabsch2"><a name="inventory"></a>Inventory for 2019/diels-grabsch2</h1>
<p><a href="#top">Jump to top</a></p>
<h2 id="primary-files">Primary files</h2>
<ul>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch2/prog.c">prog.c</a>
- entry source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch2/Makefile">Makefile</a>
- entry Makefile</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch2/prog.orig.c">prog.orig.c</a>
- original source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch2/try.sh">try.sh</a>
- how to run</li>
<li><a
href="2019_diels-grabsch2.tar.bz2">2019_diels-grabsch2.tar.bz2</a> -
download entry source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch2/prog.c">prog.c</a> - entry source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch2/Makefile">Makefile</a> - entry Makefile</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch2/prog.orig.c">prog.orig.c</a> - original source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch2/try.sh">try.sh</a> - how to run</li>
<li><a href="2019_diels-grabsch2.tar.bz2">2019_diels-grabsch2.tar.bz2</a> - download entry source</li>
</ul>
<h2 id="secondary-files">Secondary files</h2>
<ul>
<li><a href="index.html">index.html</a> - entry home page</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch2/.entry.json">.entry.json</a>
- description of entry in JSON</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch2/.gitignore">.gitignore</a>
- list of files that should not be committed under git</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch2/.entry.json">.entry.json</a> - description of entry in JSON</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch2/.gitignore">.gitignore</a> - list of files that should not be committed under git</li>
<li><a href=".path">.path</a> - directory path from top directory</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch2/README.md">README.md</a>
- markdown source for index.html</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/diels-grabsch2/README.md">README.md</a> - markdown source for index.html</li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-inventory.sh -->
+172 -253
View File
@@ -130,8 +130,8 @@
<h2 id="author"><a name="author"></a>Author:</h2>
<ul>
<li>Name: <a href="../../authors.html#Gil_Dogon">Gil Dogon</a><br>
Location: <a href="../../location.html#IL">IL</a> - <em>State of
Israel</em> (<em>Israel</em>) <br><br></li>
Location: <a href="../../location.html#IL">IL</a> - <em>State of Israel</em> (<em>Israel</em>)
<br><br></li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-author.sh -->
@@ -144,311 +144,230 @@ Israel</em> (<em>Israel</em>) <br><br></li>
<h3 id="bugs-and-misfeatures">Bugs and (Mis)features:</h3>
<p>The current status of this entry is:</p>
<pre><code>STATUS: uses gets() - change to fgets() if possible</code></pre>
<p>For more detailed information see <a
href="../../bugs.html#2019_dogon">2019 dogon bugs</a>.</p>
<p>For more detailed information see <a href="../../bugs.html#2019_dogon">2019 dogon bugs</a>.</p>
<h2 id="to-use">To use:</h2>
<div class="sourceCode" id="cb3"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> <span class="op">&lt;</span> pattern.mc</span></code></pre></div>
<h2 id="try">Try:</h2>
<div class="sourceCode" id="cb4"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./try.sh</span></span></code></pre></div>
<p>Make sure that you keep focus of windows in mind when going back and
forth to the program and the script.</p>
<p>Make sure that you keep focus of windows in mind when going back and forth to
the program and the script.</p>
<h2 id="judges-remarks">Judges’ remarks:</h2>
<p><a href="../../years.html#1991_davidguy">1991/davidguy</a>, <a
href="../../years.html#2011_blakely">2011/blakely</a>, …</p>
<p>…This entry likely concludes the IOCCC category “Cellular automata
simulators”; it would be very hard to beat it on its field.</p>
<p>FYI: The <code>.mc</code> extension stands for
<code>Golly macrocell</code> format.</p>
<p><a href="../../years.html#1991_davidguy">1991/davidguy</a>,
<a href="../../years.html#2011_blakely">2011/blakely</a>, …</p>
<p>…This entry likely concludes the IOCCC category “Cellular automata simulators”;
it would be very hard to beat it on its field.</p>
<p>FYI: The <code>.mc</code> extension stands for <code>Golly macrocell</code> 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’re using a virtual machine with less than 4 Gb of
available model RAM, you’d want to reduce the value of the Z define in
the Makefile to <code>0x10000000</code>, otherwise the entry will
promptly crash. To do this you can do:</p>
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’re using a virtual machine with less than 4 Gb of available
model RAM, you’d want to reduce the value of the Z define in the Makefile
to <code>0x10000000</code>, otherwise the entry will promptly crash. To do this you can do:</p>
<p>make clobber MEMORY=0x10000000 all</p>
<p>Notice that that value must be a power of two!</p></li>
</ul>
<p>In the interest of saving lives, this entry was not fuzzed.</p>
<h2 id="authors-remarks">Author’s remarks:</h2>
<h3 id="what-is-it">What is it?</h3>
<p>Just run with no arguments on an X11-compatible system using one of
the supplied input <code>.mc</code> files as standard input. Press
<code>-</code> several time to zoom out if necessary, then press space.
For acceleration press <code>]</code> several times. That’s rather quick
don’t you think?</p>
<p>Just run with no arguments on an X11-compatible system using one of the supplied
input <code>.mc</code> files as standard input. Press <code>-</code> several time to zoom out if
necessary, then press space. For acceleration press <code>]</code> several times. That’s
rather quick don’t you think?</p>
<h3 id="historical-timeline">Historical Timeline</h3>
<ul>
<li>Circa 3.77 - 4.28 Billion years ago: Microorganisms appear on
Earth.</li>
<li>3000 BC: Ankh symbol is used in Egyptian hieroglyph 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. Conway’s research discovers a rather minimal set of rules
that seems quite interesting. <a
href="https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life">Conway’s
Game of Life</a> gets published in <a
href="https://web.stanford.edu/class/sts145/Library/life.pdf">Martin
Gardner’s Scientific American column</a>.</li>
<li>1970s: 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 <a
href="https://en.wikipedia.org/wiki/Hashlife">Hashlife</a> algorithm.
His implementation runs on Symbolics Lisp Machines. Unrelated to that,
but in a cosmic coincidence the <a href="../../years.html#1984">first
IOCCC</a> is run!</li>
<li>December 2000: Tom Rokicki has a breakthrough implementing <a
href="https://en.wikipedia.org/wiki/Hashlife">Hashlife</a> 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 <a
href="https://en.wikipedia.org/wiki/Hashlife">hashlife</a> to the
masses.</li>
<li>Circa 3.77 - 4.28 Billion years ago: Microorganisms appear on Earth.</li>
<li>3000 BC: Ankh symbol is used in Egyptian hieroglyph 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. Conway’s research discovers a rather minimal set of rules that
seems quite interesting. <a href="https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life">Conway’s Game of
Life</a> gets published in
<a href="https://web.stanford.edu/class/sts145/Library/life.pdf">Martin Gardner’s Scientific American
column</a>.</li>
<li>1970s: 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
<a href="https://en.wikipedia.org/wiki/Hashlife">Hashlife</a> algorithm. His
implementation runs on Symbolics Lisp Machines. Unrelated to that, but in a
cosmic coincidence the <a href="../../years.html#1984">first IOCCC</a> is run!</li>
<li>December 2000: Tom Rokicki has a breakthrough implementing
<a href="https://en.wikipedia.org/wiki/Hashlife">Hashlife</a> 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 <a href="https://en.wikipedia.org/wiki/Hashlife">hashlife</a> to the masses.</li>
</ul>
<p>Which brings us to the present moment in time.</p>
<h3 id="full-documentation-and-keys-ui">Full documentation and keys
UI</h3>
<p>Yes, this program is a Conway’s Game of Life graphic simulator
implementing Bill Gosper’s hashlife algorithm. The entry’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 below, some
stuff will happen or not, there is no guarantee whatsoever.</p>
<h3 id="full-documentation-and-keys-ui">Full documentation and keys UI</h3>
<p>Yes, this program is a Conway’s Game of Life graphic simulator implementing Bill
Gosper’s hashlife algorithm. The entry’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 below, 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: <a
href="http://golly.sourceforge.net/Help/formats.html"
class="uri">http://golly.sourceforge.net/Help/formats.html</a>. Of
course only Conway’s 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’s standard distribution. Information and
credits to their designer are in the header comment of each.</p>
<p>The standard input should contain a Golly macrocell format file for a two state
automaton. See: <a href="http://golly.sourceforge.net/Help/formats.html" class="uri">http://golly.sourceforge.net/Help/formats.html</a>. Of course only
Conway’s 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’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
<code>+</code>/<code>-</code> keys (without pressing the shift on the
<code>+</code>)</li>
<li>For image navigation use the arrow keys, and zoom in and out by the <code>+</code>/<code>-</code> keys
(without pressing the shift on the <code>+</code>)</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><code>]</code>: Increase speed (time step) by a factor of 2.</li>
<li><code>[</code>: Decrease speed (time step) by a factor of 2.</li>
</ul>
<p>Notice that when going backward in time we ignore the current time
step 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 (<code>G:</code>), Internal memory allocated till
now (<code>M:</code>), and then which Level is the current macrocell
(<code>L</code>) and which zoom Scale you are watching
(<code>S</code>).</p>
<p>Notice that when going backward in time we ignore the current time step 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 (<code>G:</code>), Internal memory allocated till now (<code>M:</code>), and then which Level
is the current macrocell (<code>L</code>) and which zoom Scale you are watching (<code>S</code>).</p>
<h3 id="portability-issues">Portability issues</h3>
<p>This entry is quite portable hopefully on most modern platforms. It
assumes X Window support of course. More than 2GB of memory is
recommended. Configuration through <a href="Makefile">Makefile</a> is
provided for the display windows size and for the memory usage. The
Makefile provided configuration (<code>Z=0x20000000</code>) will need a
system with 4GB DRAM to run nicely. There are several other salient
assumptions though:</p>
<p>This entry is quite portable hopefully on most modern platforms. It assumes X
Window support of course. More than 2GB of memory is recommended. Configuration
through <a href="Makefile">Makefile</a> is provided for the display windows size and for
the memory usage. The Makefile provided configuration (<code>Z=0x20000000</code>) will need a
system with 4GB DRAM to run nicely. There are several other salient assumptions
though:</p>
<ul>
<li>The entry assumes <code>sizeof(long)==8</code>. However it actually
almost avoids using any pointers which are 64 bits these days, in order
to save space. On machines with <code>sizeof(long)==4</code> try adding
<code>#define long long long</code> …</li>
<li>The entry assumes the X11 displays default visual has 24 bit depth
(RGB).</li>
<li>The entry assumes little endianness (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 <code>long</code>s
are supported, i.e. it assumes that a <code>long</code> can be loaded
from any address that could hold an <code>int</code> otherwise. On non
<li>The entry assumes <code>sizeof(long)==8</code>. However it actually almost avoids using any
pointers which are 64 bits these days, in order to save space. On machines with
<code>sizeof(long)==4</code> try adding <code>#define long long long</code> …</li>
<li>The entry assumes the X11 displays default visual has 24 bit depth (RGB).</li>
<li>The entry assumes little endianness (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 <code>long</code>s are supported, i.e. it assumes that a
<code>long</code> can be loaded from any address that could hold an <code>int</code> otherwise. On non
antiquated X86 you’ll be fine.</li>
<li>The entry heavily relies on bitwise arithmetic (you don’t
say!).</li>
<li>The entry heavily relies on bitwise arithmetic (you don’t say!).</li>
</ul>
<h3 id="limitations">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 4GG)
it is highly recommended to set the core dump size limit to 0 in the
shell before playing with fire …</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… Anyway the amount of memory used can be controlled by the
Makefile <code>-DZ=...</code> argument. With the default <code>Z</code>,
the program will support in total about 240 million 64bit
<code>long</code>s for the internal memory, which should be sufficient
for about 100 million nodes+leafs, as each node is 3 <code>long</code>s
and each leaf is 2.</p>
<p><em>Important:</em> Makefile <code>Z</code> define must be a power of
two!</p>
<p>Zooming out past about S58 scale will enter a buggy twilight zone as
only <code>long</code> integers are used in the drawing code. Reverting
to <code>double</code>s could have remedied that, but then I’d need to
use a lot of <code>ldexp()</code>s 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 <code>2^58</code> squared is quite
a big enough universe for such a tiny program 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 <code>33333</code>
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 <code>^C</code>/intr to exit
….</p>
<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 4GG) it is highly
recommended to set the core dump size limit to 0 in the shell before playing
with fire …</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… Anyway the amount of memory
used can be controlled by the Makefile <code>-DZ=...</code> argument. With the default <code>Z</code>,
the program will support in total about 240 million 64bit <code>long</code>s for the internal
memory, which should be sufficient for about 100 million nodes+leafs, as each
node is 3 <code>long</code>s and each leaf is 2.</p>
<p><em>Important:</em> Makefile <code>Z</code> define must be a power of two!</p>
<p>Zooming out past about S58 scale will enter a buggy twilight zone as only <code>long</code>
integers are used in the drawing code. Reverting to <code>double</code>s could have remedied
that, but then I’d need to use a lot of <code>ldexp()</code>s 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 <code>2^58</code> squared is quite a big enough universe
for such a tiny program 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 <code>33333</code> 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 <code>^C</code>/intr to exit ….</p>
<h3 id="warnings">Warnings</h3>
<p>Oh don’t get me started on the torrent of litanies gcc emits when
used with <code>-Wall</code>! Does it think I have not memorized by
heart C’s precious operator precedence table (or at least have a cheat
sheet 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 <code>long</code>s printed
as <code>int</code>s but its OK too, trust me.</p>
<p>Then there’s the warning about <code>gets(3)</code> 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 don’ do that.</p>
<p>Oh don’t get me started on the torrent of litanies gcc emits when used with
<code>-Wall</code>! Does it think I have not memorized by heart C’s precious operator
precedence table (or at least have a cheat sheet 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 <code>long</code>s printed as <code>int</code>s but its OK too,
trust me.</p>
<p>Then there’s the warning about <code>gets(3)</code> 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 don’ do that.</p>
<h3 id="obfuscations">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 <code>main()</code> function
there’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 little squeak of a warning from the compiler! Macro compression
is rather sparingly used, however magic numbers abound everywhere, and
bit twiddling is magical too. Do you know for example why we have
<code>unsigned F=-1</code> ? (No warning there of course :) Hint: Later
in the program you have <code>F/=17</code>. Did that make any sense?
Further hint: print the resulting <code>F</code> in hexadecimal…</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 id="further-spoilers-engineering-and-obfuscation-galore">Further
spoilers, engineering, and obfuscation galore:</h3>
<p>Those wait for you, curious and intrepid reader, in the attached <a
href="apholife.c">apholife.c</a> 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
<code>ldexp()</code>s 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, it’s not nice and tame, it even has an escape key,
usage message, and to top it all it even avoids
<code>gets(3)</code>!</p>
<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 <code>main()</code> function there’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 little squeak of a warning from the
compiler! Macro compression is rather sparingly used, however magic numbers
abound everywhere, and bit twiddling is magical too. Do you know for example why
we have <code>unsigned F=-1</code> ? (No warning there of course :) Hint: Later in the
program you have <code>F/=17</code>. Did that make any sense? Further hint: print the
resulting <code>F</code> in hexadecimal…</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 id="further-spoilers-engineering-and-obfuscation-galore">Further spoilers, engineering, and obfuscation galore:</h3>
<p>Those wait for you, curious and intrepid reader, in the attached
<a href="apholife.c">apholife.c</a> 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 <code>ldexp()</code>s 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, it’s not nice and tame, it even has an escape key, usage
message, and to top it all it even avoids <code>gets(3)</code>!</p>
<h3 id="special-thanks">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 <code>8*8</code> leaf:</p>
<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 <code>8*8</code> leaf:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="dt">unsigned</span> <span class="dt">long</span> life8x8<span class="op">(</span><span class="dt">long</span> a<span class="op">)</span> <span class="op">{</span> <span class="dt">unsigned</span> <span class="dt">long</span> aw <span class="op">=</span> a <span class="op">&lt;&lt;</span> <span class="dv">1</span><span class="op">,</span> ae <span class="op">=</span> a <span class="op">&gt;&gt;</span> <span class="dv">1</span><span class="op">,</span> s0 <span class="op">=</span> aw</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="op">^</span> ae<span class="op">,</span> s1 <span class="op">=</span> aw <span class="op">&amp;</span> ae<span class="op">,</span> hs0 <span class="op">=</span> s0 <span class="op">^</span> a<span class="op">,</span> hs1 <span class="op">=</span> <span class="op">(</span>s0 <span class="op">&amp;</span> a<span class="op">)</span> <span class="op">|</span> s1<span class="op">,</span> hs0w8 <span class="op">=</span> hs0 <span class="op">&gt;&gt;</span> <span class="dv">8</span><span class="op">,</span> hs0e8 <span class="op">=</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>hs0 <span class="op">&lt;&lt;</span> <span class="dv">8</span><span class="op">,</span> hs1w8 <span class="op">=</span> hs1 <span class="op">&gt;&gt;</span> <span class="dv">8</span><span class="op">,</span> hs1e8 <span class="op">=</span> hs1 <span class="op">&lt;&lt;</span> <span class="dv">8</span><span class="op">,</span> ts0 <span class="op">=</span> hs0w8 <span class="op">^</span> hs0e8<span class="op">,</span> ts1 <span class="op">=</span> <span class="op">(</span>hs0w8</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="op">&amp;</span> hs0e8<span class="op">)</span> <span class="op">|</span> <span class="op">(</span>ts0 <span class="op">&amp;</span> s0<span class="op">);</span> <span class="cf">return</span> <span class="op">(</span>hs1w8 <span class="op">^</span> hs1e8 <span class="op">^</span> ts1 <span class="op">^</span> s1<span class="op">)</span> <span class="op">&amp;</span> <span class="op">((</span>hs1w8 <span class="op">|</span> hs1e8<span class="op">)</span> <span class="op">^</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="op">(</span>ts1 <span class="op">|</span> s1<span class="op">))</span> <span class="op">&amp;</span> <span class="op">((</span>ts0 <span class="op">^</span> s0<span class="op">)</span> <span class="op">|</span> a<span class="op">);</span> <span class="op">}</span></span></code></pre></div>
<p>This uses only 19 bitwise operations and six shifts to calculate the
inner 6x6 next generation bits of the input 8x8 !</p>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0
License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights
Reserved. You are free to share and adapt this file under the terms of
this license:</p>
<p>This uses only 19 bitwise operations and six shifts to calculate the inner 6x6
next generation bits of the input 8x8 !</p>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0 License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved.
You are free to share and adapt this file under the terms of this license:</p>
<pre><code>Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)</code></pre>
<p>For more information, see:
https://creativecommons.org/licenses/by-sa/4.0/</p>
<p>For more information, see: https://creativecommons.org/licenses/by-sa/4.0/</p>
<!-- END: this line ends content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
<!-- START: this line starts content for HTML phase 22 by: bin/output-index-inventory.sh via bin/md2html.sh -->
<!-- START: this line starts content generated by: bin/output-index-inventory.sh -->
<h1 id="inventory-for-2019dogon"><a name="inventory"></a>Inventory for
2019/dogon</h1>
<h1 id="inventory-for-2019dogon"><a name="inventory"></a>Inventory for 2019/dogon</h1>
<p><a href="#top">Jump to top</a></p>
<h2 id="primary-files">Primary files</h2>
<ul>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/prog.c">prog.c</a>
- entry source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/Makefile">Makefile</a>
- entry Makefile</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/prog.orig.c">prog.orig.c</a>
- original source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/glider.mc">glider.mc</a>
- Golly macrocell input file</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/gotts-dots.mc">gotts-dots.mc</a>
- Golly macrocell input file</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/infinite.mc">infinite.mc</a>
- Golly macrocell input file</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/infinite_10cell.mc">infinite_10cell.mc</a>
- Golly macrocell input file</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/infinite_5x5.mc">infinite_5x5.mc</a>
- Golly macrocell input file</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/infinite_minimal.mc">infinite_minimal.mc</a>
- Golly macrocell input file</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/jagged.mc">jagged.mc</a>
- Golly macrocell input file</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/message.mc">message.mc</a>
- Golly macrocell input file</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/metacatacryst.mc">metacatacryst.mc</a>
- Golly macrocell input file</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/metapixel-parity64.mc">metapixel-parity64.mc</a>
- Golly macrocell input file</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/mosquito5.mc">mosquito5.mc</a>
- Golly macrocell input file</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/try.sh">try.sh</a>
- how to run</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/unlimited-novelty.mc">unlimited-novelty.mc</a>
- Golly macrocell input file</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/apholife.c">apholife.c</a>
- partially obfuscated source</li>
<li><a href="2019_dogon.tar.bz2">2019_dogon.tar.bz2</a> - download entry
source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/prog.c">prog.c</a> - entry source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/Makefile">Makefile</a> - entry Makefile</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/prog.orig.c">prog.orig.c</a> - original source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/glider.mc">glider.mc</a> - Golly macrocell input file</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/gotts-dots.mc">gotts-dots.mc</a> - Golly macrocell input file</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/infinite.mc">infinite.mc</a> - Golly macrocell input file</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/infinite_10cell.mc">infinite_10cell.mc</a> - Golly macrocell input file</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/infinite_5x5.mc">infinite_5x5.mc</a> - Golly macrocell input file</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/infinite_minimal.mc">infinite_minimal.mc</a> - Golly macrocell input file</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/jagged.mc">jagged.mc</a> - Golly macrocell input file</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/message.mc">message.mc</a> - Golly macrocell input file</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/metacatacryst.mc">metacatacryst.mc</a> - Golly macrocell input file</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/metapixel-parity64.mc">metapixel-parity64.mc</a> - Golly macrocell input file</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/mosquito5.mc">mosquito5.mc</a> - Golly macrocell input file</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/try.sh">try.sh</a> - how to run</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/unlimited-novelty.mc">unlimited-novelty.mc</a> - Golly macrocell input file</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/apholife.c">apholife.c</a> - partially obfuscated source</li>
<li><a href="2019_dogon.tar.bz2">2019_dogon.tar.bz2</a> - download entry source</li>
</ul>
<h2 id="secondary-files">Secondary files</h2>
<ul>
<li><a href="index.html">index.html</a> - entry home page</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/.entry.json">.entry.json</a>
- description of entry in JSON</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/.gitignore">.gitignore</a>
- list of files that should not be committed under git</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/.entry.json">.entry.json</a> - description of entry in JSON</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/.gitignore">.gitignore</a> - list of files that should not be committed under git</li>
<li><a href=".path">.path</a> - directory path from top directory</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/README.md">README.md</a>
- markdown source for index.html</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/dogon/README.md">README.md</a> - markdown source for index.html</li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-inventory.sh -->
+105 -162
View File
@@ -129,9 +129,9 @@
<h2 id="author"><a name="author"></a>Author:</h2>
<ul>
<li>Name: <a href="../../authors.html#Etienne_Duble">Etienne
Duble</a><br> Location: <a href="../../location.html#FR">FR</a> -
<em>French Republic</em> (<em>France</em>) <br><br></li>
<li>Name: <a href="../../authors.html#Etienne_Duble">Etienne Duble</a><br>
Location: <a href="../../location.html#FR">FR</a> - <em>French Republic</em> (<em>France</em>)
<br><br></li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-author.sh -->
@@ -141,14 +141,12 @@ Duble</a><br> Location: <a href="../../location.html#FR">FR</a> -
<h2 id="to-build">To build:</h2>
<div class="sourceCode" id="cb1"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span></span></code></pre></div>
<p>There is an alternate version, the original, which does not work well
in macOS. See <a href="#alternate-code">Alternate code</a> below if you
are curious.</p>
<p>There is an alternate version, the original, which does not work well in macOS.
See <a href="#alternate-code">Alternate code</a> below if you are curious.</p>
<h3 id="bugs-and-misfeatures">Bugs and (Mis)features:</h3>
<p>The current status of this entry is:</p>
<pre><code>STATUS: INABIAF - please **DO NOT** fix</code></pre>
<p>For more detailed information see <a
href="../../bugs.html#2019_duble">2019 duble bugs</a>.</p>
<p>For more detailed information see <a href="../../bugs.html#2019_duble">2019 duble bugs</a>.</p>
<h2 id="to-use">To use:</h2>
<div class="sourceCode" id="cb3"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> file</span></code></pre></div>
<h2 id="try">Try:</h2>
@@ -164,15 +162,12 @@ href="../../bugs.html#2019_duble">2019 duble bugs</a>.</p>
<hr />
<ul>
<li><strong>Arrow keys</strong>: move cursor.</li>
<li><code>p</code> key: enter <em>pen</em> mode (type <strong>p</strong>
again to return to the default <em>move</em> mode).</li>
<li><code>l</code> 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><code>c</code> key: cycle through a small set of different
<em>colors</em>.</li>
<li><code>q</code> key: quit the editor. The drawing is automatically
saved.</li>
<li><code>p</code> key: enter <em>pen</em> mode (type <strong>p</strong> again to return to the default <em>move</em>
mode).</li>
<li><code>l</code> 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><code>c</code> key: cycle through a small set of different <em>colors</em>.</li>
<li><code>q</code> 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>
@@ -180,202 +175,150 @@ the editor.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ex">/tmp/drawing</span></span></code></pre></div>
<p>i.e. execute the file.</p>
<hr />
<p>WARNING: if the file is deleted it might lock any session still in
use. These will have to be killed from another shell session or by
closing the terminal tab (in other words don’t do this from the
console!). If the file cannot be opened in the beginning this will also
happen. This is discussed in <a href="../../bugs.html#2019_duble">2019
duble bugs</a>.</p>
<p>NOTE: this entry might leave sockets lying about in the current
working directory which you’ll have to delete manually. This is also
discussed in <a href="../../bugs.html#2019_duble">2019 duble
bugs</a>.</p>
<p>WARNING: if the file is deleted it might lock any session still in use. These
will have to be killed from another shell session or by closing the terminal tab
(in other words don’t do this from the console!). If the file cannot be opened
in the beginning this will also happen. This is discussed in
<a href="../../bugs.html#2019_duble">2019 duble bugs</a>.</p>
<p>NOTE: this entry might leave sockets lying about in the current working
directory which you’ll have to delete manually. This is also discussed in
<a href="../../bugs.html#2019_duble">2019 duble bugs</a>.</p>
<h2 id="alternate-code">Alternate code:</h2>
<p>An alternate version of this entry, <a
href="prog.alt.c">prog.alt.c</a>, is provided. This alternate code might
not work as well in macOS.</p>
<p>An alternate version of this entry, <a href="prog.alt.c">prog.alt.c</a>, is provided. This
alternate code might not work as well in macOS.</p>
<h3 id="alternate-build">Alternate build:</h3>
<div class="sourceCode" id="cb9"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span> alt</span></code></pre></div>
<h3 id="alternate-use">Alternate use:</h3>
<p>Use <code>prog.alt</code> as you would <code>prog</code> above.</p>
<h2 id="judges-remarks">Judges’ remarks:</h2>
<p>After starting the program, use the cursor keys, then try some modes,
like <code>p</code> or <code>l</code> (they toggle).</p>
<p>After starting the program, use the cursor keys, then try some modes, like <code>p</code>
or <code>l</code> (they toggle).</p>
<h2 id="authors-remarks">Author’s remarks:</h2>
<h3 id="introduction">Introduction:</h3>
<p>This program is a <strong>graphics editor</strong>, running in 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>
<p>This program is a <strong>graphics editor</strong>, running in 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 id="getting-started">Getting started:</h3>
<p>The program can run on Linux, FreeBSD, macOS, and in most terminals.
See section <a href="#limits-portability">Limits, Portability</a> 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>
<div class="sourceCode" id="cb10"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> /tmp/drawing</span></code></pre></div>
<p>(If not started this way, with a file, <code>prog</code> will refuse
to start.)</p>
See section <a href="#limits-portability">Limits, Portability</a> 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>
<div class="sourceCode" id="cb10"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> /tmp/drawing</span></code></pre></div>
<p>(If not started this way, with a file, <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>
<p>If someone else (or another <em>instance of yourself</em>, maybe?) is already
editing this file, you will join the session!</p>
<h3 id="edit-features">Edit features:</h3>
<ul>
<li><strong>arrow keys</strong>: move cursor.</li>
<li><code>p</code> key: enter <em>pen</em> mode (type <strong>p</strong>
again to return to the default <em>move</em> mode).</li>
<li><code>l</code> 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><code>c</code> key: cycle through a small set of different
<em>colors</em>.</li>
<li><code>q</code> key: quit the editor. The drawing is automatically
saved.</li>
<li><code>p</code> key: enter <em>pen</em> mode (type <strong>p</strong> again to return to the default <em>move</em> mode).</li>
<li><code>l</code> 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><code>c</code> key: cycle through a small set of different <em>colors</em>.</li>
<li><code>q</code> 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 id="bonus-features">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>
<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 id="obfuscation">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 <code>stdlib.h</code> call results are
inferred.</li>
<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 <code>stdlib.h</code> 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>
<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 id="a-few-more-things">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:
<a href="http://c-faq.com/ansi/constasconst.html"
class="uri">http://c-faq.com/ansi/constasconst.html</a>)</p>
<p>If your keyboard has no arrow keys, you can probably find alternate
keys by reading the source code.</p>
<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: <a href="http://c-faq.com/ansi/constasconst.html" class="uri">http://c-faq.com/ansi/constasconst.html</a>)</p>
<p>If your keyboard has no arrow keys, you can probably find alternate keys by
reading the source code.</p>
<h3 id="limits-portability">Limits, Portability:</h3>
<p>I tested the program on several Linux systems, on FreeBSD 12, and on
macOS (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.
<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 macOS.
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>
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 id="drawing-area-size">Drawing area size:</h3>
<h4 id="the-drawing-area-size-is-set-at-compilation-time">The drawing
area size is set at compilation time:</h4>
<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>
<div class="sourceCode" id="cb11"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span> clobber fullscreen</span></code></pre></div>
<h4 id="the-drawing-area-size-is-set-at-compilation-time">The drawing area size is set at compilation time:</h4>
<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>
<div class="sourceCode" id="cb11"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span> clobber fullscreen</span></code></pre></div>
<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>
<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 id="prog.c-vs-prog.alt.c"><a href="prog.c">prog.c</a> vs <a
href="prog.alt.c">prog.alt.c</a></h3>
<p>The file <a href="prog.alt.c">prog.alt.c</a> is the one I
submitted.</p>
<p>The judges proposed a small update: the program was using macro
<code>FD_SET</code> inside an expression, which breaks compilation on
macOS. 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 macOS. 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 <a
href="check-os.sh">check-os.sh</a>). I tried hard to tune macOS the
same, but failed.</p>
<p>The simple fact the Judges proposed this update meant they wish it
could work on Mac. And if the 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… And I obtained <a href="prog.c">prog.c</a>.
With this version, no need to touch <code>sysctl</code> parameters, and
it works on macOS too! I must confess it was challenging to remain below
the size limit with this little change.</p>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0
License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights
Reserved. You are free to share and adapt this file under the terms of
this license:</p>
<h3 id="prog.c-vs-prog.alt.c"><a href="prog.c">prog.c</a> vs <a href="prog.alt.c">prog.alt.c</a></h3>
<p>The file <a href="prog.alt.c">prog.alt.c</a> is the one I submitted.</p>
<p>The judges proposed a small update: the program was using macro <code>FD_SET</code> inside an
expression, which breaks compilation on macOS. 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 macOS. 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
<a href="check-os.sh">check-os.sh</a>). I tried hard to tune macOS the same, but failed.</p>
<p>The simple fact the Judges proposed this update meant they wish it could work on
Mac. And if the 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… And I obtained
<a href="prog.c">prog.c</a>. With this version, no need to touch <code>sysctl</code> parameters, and
it works on macOS too! I must confess it was challenging to remain below the
size limit with this little change.</p>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0 License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved.
You are free to share and adapt this file under the terms of this license:</p>
<pre><code>Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)</code></pre>
<p>For more information, see:
https://creativecommons.org/licenses/by-sa/4.0/</p>
<p>For more information, see: https://creativecommons.org/licenses/by-sa/4.0/</p>
<!-- END: this line ends content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
<!-- START: this line starts content for HTML phase 22 by: bin/output-index-inventory.sh via bin/md2html.sh -->
<!-- START: this line starts content generated by: bin/output-index-inventory.sh -->
<h1 id="inventory-for-2019duble"><a name="inventory"></a>Inventory for
2019/duble</h1>
<h1 id="inventory-for-2019duble"><a name="inventory"></a>Inventory for 2019/duble</h1>
<p><a href="#top">Jump to top</a></p>
<h2 id="primary-files">Primary files</h2>
<ul>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/duble/prog.c">prog.c</a>
- entry source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/duble/Makefile">Makefile</a>
- entry Makefile</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/duble/prog.alt.c">prog.alt.c</a>
- alternative source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/duble/prog.orig.c">prog.orig.c</a>
- original source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/duble/check-os.sh">check-os.sh</a>
- check the operating system for compatibility</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/duble/fullscreen.sh">fullscreen.sh</a>
- determine full screen size for make fullscreen</li>
<li><a href="2019_duble.tar.bz2">2019_duble.tar.bz2</a> - download entry
source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/duble/prog.c">prog.c</a> - entry source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/duble/Makefile">Makefile</a> - entry Makefile</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/duble/prog.alt.c">prog.alt.c</a> - alternative source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/duble/prog.orig.c">prog.orig.c</a> - original source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/duble/check-os.sh">check-os.sh</a> - check the operating system for compatibility</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/duble/fullscreen.sh">fullscreen.sh</a> - determine full screen size for make fullscreen</li>
<li><a href="2019_duble.tar.bz2">2019_duble.tar.bz2</a> - download entry source</li>
</ul>
<h2 id="secondary-files">Secondary files</h2>
<ul>
<li><a href="index.html">index.html</a> - entry home page</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/duble/.entry.json">.entry.json</a>
- description of entry in JSON</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/duble/.gitignore">.gitignore</a>
- list of files that should not be committed under git</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/duble/.entry.json">.entry.json</a> - description of entry in JSON</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/duble/.gitignore">.gitignore</a> - list of files that should not be committed under git</li>
<li><a href=".path">.path</a> - directory path from top directory</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/duble/README.md">README.md</a>
- markdown source for index.html</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/duble/README.md">README.md</a> - markdown source for index.html</li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-inventory.sh -->
+23 -51
View File
@@ -141,31 +141,25 @@ Location: <a href="../../location.html#JP">JP</a> - <em>Japan</em>
<h2 id="to-build">To build:</h2>
<div class="sourceCode" id="cb1"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span></span></code></pre></div>
<p>NOTE: the use of the C compiler optimiser was disabled and
<code>-g</code> was enabled for this entry because it is SUPPOSED to
crash and it needs debugging symbols.</p>
<p>NOTE: the use of the C compiler optimiser was disabled and <code>-g</code> was enabled for
this entry because it is SUPPOSED to crash and it needs debugging symbols.</p>
<h3 id="bugs-and-misfeatures">Bugs and (Mis)features:</h3>
<p>The current status of this entry is:</p>
<pre><code>STATUS: INABIAF - please **DO NOT** fix</code></pre>
<p>For more detailed information see <a
href="../../bugs.html#2019_endoh">2019 endoh bugs</a>.</p>
<p>For more detailed information see <a href="../../bugs.html#2019_endoh">2019 endoh bugs</a>.</p>
<h2 id="to-use">To use:</h2>
<div class="sourceCode" id="cb3"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span></span></code></pre></div>
<h2 id="try">Try:</h2>
<p>If you have <code>gdb(1)</code> installed:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./try.sh</span></span></code></pre></div>
<p>Note that in macOS installing <code>gdb(1)</code> takes multiple
steps - it’s not just a matter of installing <code>gdb(1)</code> and
that’s that. The <a href="try.sh">try.sh</a> script has only been tested
with linux.</p>
<p>Note that in macOS installing <code>gdb(1)</code> takes multiple steps - it’s not just a
matter of installing <code>gdb(1)</code> and that’s that. The <a href="try.sh">try.sh</a> script has
only been tested with linux.</p>
<p>You might also wish to try:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="fu">gdb</span> ./prog <span class="kw">||</span> <span class="ex">lldb</span> ./prog</span></code></pre></div>
<p>and then type in <code>r</code> (to run program) and then
<code>bt</code> (for backtrace).</p>
<p>and then type in <code>r</code> (to run program) and then <code>bt</code> (for backtrace).</p>
<h2 id="judges-remarks">Judges’ remarks:</h2>
<p>The purpose of this program is to crash. You’ll want to have
memorized <code>man 7 ascii</code> when debugging it to reveal its
purpose.</p>
<p>The purpose of this program is to crash. You’ll want to have memorized <code>man 7 ascii</code> when debugging it to reveal its purpose.</p>
<h2 id="authors-remarks">Author’s remarks:</h2>
<h3 id="backtrace-quine">backtrace quine:</h3>
<p>Compile prog.c with no optimization.</p>
@@ -217,59 +211,37 @@ Program received signal SIGSEGV, Segmentation fault.
#7 0x0000555555555747 in x65 () at prog.c:101
...</code></pre>
<p>By using this, you can confirm that it is actually a quine.</p>
<div class="sourceCode" id="cb12"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="fu">gdb</span> <span class="at">-q</span> <span class="at">-x</span> prog.c ./prog <span class="kw">|</span> <span class="fu">sed</span> <span class="at">-n</span> <span class="at">-r</span> <span class="st">&#39;s/#.*:([0-9]+)/\1/p&#39;</span> <span class="kw">|</span> <span class="fu">awk</span> <span class="st">&#39;{printf &quot;%c&quot;,$1}&#39;</span> <span class="op">&gt;</span> prog2.c</span>
<div class="sourceCode" id="cb12"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="fu">gdb</span> <span class="at">-q</span> <span class="at">-x</span> prog.c ./prog <span class="kw">|</span> <span class="fu">sed</span> <span class="at">-n</span> <span class="at">-r</span> <span class="st">&#39;s/#.*:([0-9]+)/\1/p&#39;</span> <span class="kw">|</span> <span class="fu">awk</span> <span class="st">&#39;{printf &quot;%c&quot;,$1}&#39;</span> <span class="op">&gt;</span> prog2.c</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="fu">diff</span> prog.c prog2.c</span></code></pre></div>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0
License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights
Reserved. You are free to share and adapt this file under the terms of
this license:</p>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0 License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved.
You are free to share and adapt this file under the terms of this license:</p>
<pre><code>Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)</code></pre>
<p>For more information, see:
https://creativecommons.org/licenses/by-sa/4.0/</p>
<p>For more information, see: https://creativecommons.org/licenses/by-sa/4.0/</p>
<!-- END: this line ends content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
<!-- START: this line starts content for HTML phase 22 by: bin/output-index-inventory.sh via bin/md2html.sh -->
<!-- START: this line starts content generated by: bin/output-index-inventory.sh -->
<h1 id="inventory-for-2019endoh"><a name="inventory"></a>Inventory for
2019/endoh</h1>
<h1 id="inventory-for-2019endoh"><a name="inventory"></a>Inventory for 2019/endoh</h1>
<p><a href="#top">Jump to top</a></p>
<h2 id="primary-files">Primary files</h2>
<ul>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/endoh/prog.c">prog.c</a>
- entry source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/endoh/Makefile">Makefile</a>
- entry Makefile</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/endoh/prog.orig.c">prog.orig.c</a>
- original source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/endoh/try.sh">try.sh</a>
- how to run</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/endoh/ascii.c">ascii.c</a>
- shows character value of ASCII</li>
<li><a href="2019_endoh.tar.bz2">2019_endoh.tar.bz2</a> - download entry
source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/endoh/prog.c">prog.c</a> - entry source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/endoh/Makefile">Makefile</a> - entry Makefile</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/endoh/prog.orig.c">prog.orig.c</a> - original source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/endoh/try.sh">try.sh</a> - how to run</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/endoh/ascii.c">ascii.c</a> - shows character value of ASCII</li>
<li><a href="2019_endoh.tar.bz2">2019_endoh.tar.bz2</a> - download entry source</li>
</ul>
<h2 id="secondary-files">Secondary files</h2>
<ul>
<li><a href="index.html">index.html</a> - entry home page</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/endoh/.entry.json">.entry.json</a>
- description of entry in JSON</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/endoh/.gitignore">.gitignore</a>
- list of files that should not be committed under git</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/endoh/.entry.json">.entry.json</a> - description of entry in JSON</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/endoh/.gitignore">.gitignore</a> - list of files that should not be committed under git</li>
<li><a href=".path">.path</a> - directory path from top directory</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/endoh/README.md">README.md</a>
- markdown source for index.html</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/endoh/README.md">README.md</a> - markdown source for index.html</li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-inventory.sh -->
+148 -210
View File
@@ -130,8 +130,8 @@
<h2 id="author"><a name="author"></a>Author:</h2>
<ul>
<li>Name: <a href="../../authors.html#Edward_Giles">Edward Giles</a><br>
Location: <a href="../../location.html#AU">AU</a> - <em>Commonwealth of
Australia</em> (<em>Australia</em>) <br><br></li>
Location: <a href="../../location.html#AU">AU</a> - <em>Commonwealth of Australia</em> (<em>Australia</em>)
<br><br></li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-author.sh -->
@@ -145,279 +145,217 @@ Australia</em> (<em>Australia</em>) <br><br></li>
<div class="sourceCode" id="cb2"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> infile.wav outfile.wav</span></code></pre></div>
<h2 id="try">Try:</h2>
<div class="sourceCode" id="cb3"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./try.sh</span></span></code></pre></div>
<p>NOTE: <code>play</code>, which <a href="try.sh">try.sh</a> uses,
comes from SoX, the Swiss Army Knife of sound processing programs. If
you don’t have this installed, see <a href="../../faq.html#sox">FAQ
3.10: How do I compile and use an IOCCC entry that requires
sound</a>.</p>
<p>NOTE: <code>play</code>, which <a href="try.sh">try.sh</a> uses, comes from SoX, the Swiss Army Knife
of sound processing programs. If you don’t have this installed, see <a href="../../faq.html#sox">FAQ 3.10:
How do I compile and use an IOCCC entry that requires sound</a>.</p>
<h2 id="judges-remarks">Judges’ remarks:</h2>
<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’t
waste another minute! Record yourself, send the audio file through this
entry, and let your callers be surprised.</p>
<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’t waste another minute!
Record yourself, send the audio file through this entry, and let your callers be
surprised.</p>
<h2 id="authors-remarks">Author’s remarks:</h2>
<h3 id="description">Description:</h3>
<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><a href="BlockDiagram.png">BlockDiagram.png</a> 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><a href="MonodyVocals.wav">MonodyVocals.wav</a> 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’s C/C++ compiler. However, the latter reports warnings about
loss of information when converting <code>float</code>s, 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>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><a href="BlockDiagram.png">BlockDiagram.png</a> 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><a href="MonodyVocals.wav">MonodyVocals.wav</a> 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’s C/C++ compiler. However,
the latter reports warnings about loss of information when converting <code>float</code>s,
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>
<h4 id="how-to-use">How to use:</h4>
<div class="sourceCode" id="cb4"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> input [output [size [dry [wet <span class="pp">[</span><span class="ss">damping</span><span class="pp">]</span>]]]]</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="ex">prog.exe</span> input [output [size [dry [wet <span class="pp">[</span><span class="ss">damping</span><span class="pp">]</span>]]]]</span></code></pre></div>
<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 (“dry” in audio
terminology) to add to the output. Optional, default 0.3 or 30%.</li>
<li><code>wet</code>: The amount of processed (“wet”) 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 “harsh” and more “muffled”. Optional, default
0.06 or 6%.</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 (“dry” in audio terminology) to add to
the output. Optional, default 0.3 or 30%.</li>
<li><code>wet</code>: The amount of processed (“wet”) 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 “harsh” and
more “muffled”. 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 “dry” to
“wet”, to give a more pleasant result:</p>
<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 “dry” to “wet”, to give a more
pleasant result:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> in.wav out.wav 1.8 80% 15%</span></code></pre></div>
<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’t use
these features are very common. The program validates the input file, so
passing it a file it can’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>
<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’t use these features are very common. The program validates
the input file, so passing it a file it can’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>
<h3 id="assumptions">Assumptions:</h3>
<ol type="1">
<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’s-complement,
<code>sizeof(int16_t) == 2</code> and
<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’s-complement, <code>sizeof(int16_t) == 2</code> and
<code>sizeof(int32_t) == 4</code>.</li>
</ol>
<h3 id="obfuscations">Obfuscations</h3>
<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>
<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>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>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>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’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>
<p>Note that no part of the above description of the code’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
<code>16</code>.</li>
<li><code>i</code> is the number of delay-lines to allocate and use
(currently <code>24</code>).</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>k</code> is just a general-purpose replacement for <code>16</code>.</li>
<li><code>i</code> is the number of delay-lines to allocate and use (currently <code>24</code>).</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’s body are matched with the <code>]</code>s
<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’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>
<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>
<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 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>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>
<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 “encrypted” by
breaking the string into 4-byte chunks (by casting it to an
<code>int32_t*</code>), and then XORing the sequence of
<code>int</code>s with a known numeric sequence. The “decryption” 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>
<p>All of the strings are concatenated together and “encrypted” by breaking the
string into 4-byte chunks (by casting it to an <code>int32_t*</code>), and then XORing the
sequence of <code>int</code>s with a known numeric sequence. The “decryption” 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> -&gt; <code>1[X]</code></li>
<li><code>f[14]</code> -&gt; <code>10[f+4]</code></li>
<li><code>X[0]</code> -&gt; <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
<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 conjunction with the comma operator to
further obscure where the data ends up. For example:</p>
<p>This technique is used in conjunction 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
<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>
<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>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0
License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights
Reserved. You are free to share and adapt this file under the terms of
this license:</p>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0 License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved.
You are free to share and adapt this file under the terms of this license:</p>
<pre><code>Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)</code></pre>
<p>For more information, see:
https://creativecommons.org/licenses/by-sa/4.0/</p>
<p>For more information, see: https://creativecommons.org/licenses/by-sa/4.0/</p>
<!-- END: this line ends content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
<!-- START: this line starts content for HTML phase 22 by: bin/output-index-inventory.sh via bin/md2html.sh -->
<!-- START: this line starts content generated by: bin/output-index-inventory.sh -->
<h1 id="inventory-for-2019giles"><a name="inventory"></a>Inventory for
2019/giles</h1>
<h1 id="inventory-for-2019giles"><a name="inventory"></a>Inventory for 2019/giles</h1>
<p><a href="#top">Jump to top</a></p>
<h2 id="primary-files">Primary files</h2>
<ul>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/giles/prog.c">prog.c</a>
- entry source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/giles/Makefile">Makefile</a>
- entry Makefile</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/giles/prog.orig.c">prog.orig.c</a>
- original source</li>
<li><a href="BlockDiagram.png">BlockDiagram.png</a> - reverb algorithm
block-diagram of internal structure</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/giles/try.sh">try.sh</a>
- how to run</li>
<li><a href="MonodyVocals.wav">MonodyVocals.wav</a> - Monody by
TheFatRat featuring Laura Brehm</li>
<li><a href="2019_giles.tar.bz2">2019_giles.tar.bz2</a> - download entry
source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/giles/prog.c">prog.c</a> - entry source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/giles/Makefile">Makefile</a> - entry Makefile</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/giles/prog.orig.c">prog.orig.c</a> - original source</li>
<li><a href="BlockDiagram.png">BlockDiagram.png</a> - reverb algorithm block-diagram of internal structure</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/giles/try.sh">try.sh</a> - how to run</li>
<li><a href="MonodyVocals.wav">MonodyVocals.wav</a> - Monody by TheFatRat featuring Laura Brehm</li>
<li><a href="2019_giles.tar.bz2">2019_giles.tar.bz2</a> - download entry source</li>
</ul>
<h2 id="secondary-files">Secondary files</h2>
<ul>
<li><a href="index.html">index.html</a> - entry home page</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/giles/.entry.json">.entry.json</a>
- description of entry in JSON</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/giles/.gitignore">.gitignore</a>
- list of files that should not be committed under git</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/giles/.entry.json">.entry.json</a> - description of entry in JSON</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/giles/.gitignore">.gitignore</a> - list of files that should not be committed under git</li>
<li><a href=".path">.path</a> - directory path from top directory</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/giles/README.md">README.md</a>
- markdown source for index.html</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/giles/README.md">README.md</a> - markdown source for index.html</li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-inventory.sh -->
+50 -79
View File
@@ -123,32 +123,27 @@
<!-- END: this line ends content from: inc/before-content.default.html -->
<!-- START: this line starts content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
<h1 id="twenty-sixth-international-obfuscated-c-code-contest">Twenty
Sixth International Obfuscated C Code Contest</h1>
<h1 id="twenty-sixth-international-obfuscated-c-code-contest">Twenty Sixth International Obfuscated C Code Contest</h1>
<h2 id="standard-ioccc-stuff">Standard IOCCC stuff</h2>
<p>View the <code>index.html</code> web page for the given winning entry
for information on how on how to compile it and how to run the winning
program. Look at the winning source and try to figure how it does what
it does! You may then wish to look at the Author’s remarks for even more
details.</p>
<p>The primary site can be found at <a
href="https://www.ioccc.org">www.ioccc.org</a>.</p>
<p>Use <code>make</code> to compile entries. It is possible that on
non-Unix / non-Linux systems the Makefile needs to be changed. See the
Makefile for details.</p>
<p>Read over the Makefile and index.html files for compile/build issues.
Your system may require certain changes (add or remove a library, add or
remove a <code>#define</code>).</p>
<p>View the <code>index.html</code> web page for the given winning entry for information on how
on how to compile it and how to run the winning program.
Look at the winning source and try to figure how it does what it does!
You may then wish to look at the Author’s remarks for even more details.</p>
<p>The primary site can be found at <a href="https://www.ioccc.org">www.ioccc.org</a>.</p>
<p>Use <code>make</code> to compile entries. It is possible that on non-Unix / non-Linux
systems the Makefile needs to be changed. See the Makefile for details.</p>
<p>Read over the Makefile and index.html files for compile/build issues. Your
system may require certain changes (add or remove a library, add or remove a
<code>#define</code>).</p>
<p>Some C compilers are not quite as good as they should be. If yours is
lacking, you may need to compile using clang or gcc instead of your
local compiler.</p>
<h2 id="remarks-on-some-of-the-winning-entries">Remarks on some of the
winning entries</h2>
lacking, you may need to compile using clang or gcc instead of your local
compiler.</p>
<h2 id="remarks-on-some-of-the-winning-entries">Remarks on some of the winning entries</h2>
<p>This year’s winning entries are impressive!</p>
<p>The <a href="endoh/index.html">“Most in need of debugging”
(endoh)</a> is very inventive in a way it produces its own text!</p>
<p>The <a href="ciura/index.html">“Most likely to be awarded”
(ciura)</a> has an amazing vocabulary!</p>
<p>The <a href="endoh/index.html">“Most in need of debugging” (endoh)</a> is very inventive in
a way it produces its own text!</p>
<p>The <a href="ciura/index.html">“Most likely to be awarded” (ciura)</a> has an amazing
vocabulary!</p>
<p>There are again nods to entries of the years:</p>
<pre><code>[1991/davidguy](../years.html#1991_davidguy)
[2011/blakely](../years.html#2011_blakely)</code></pre>
@@ -156,79 +151,55 @@ winning entries</h2>
<pre><code>We tend to dislike programs that:
...
are rather similar to previous entries</code></pre>
<p>because the entry <a href="2019/dogon/index.html">2019/dogon</a>
appropriately pays homage to past entries without blatantly reusing
their code.</p>
<p>…We’ll stop spouting spoilers now. Have fun exploring all the
entries!</p>
<h2 id="remarks-on-some-of-submissions-that-did-not-win">Remarks on some
of submissions that did not win</h2>
<p>because the entry <a href="2019/dogon/index.html">2019/dogon</a> appropriately pays homage
to past entries without blatantly reusing their code.</p>
<p>…We’ll stop spouting spoilers now. Have fun exploring all the entries!</p>
<h2 id="remarks-on-some-of-submissions-that-did-not-win">Remarks on some of submissions that did not win</h2>
<p>Some entries tried to get around the size limit by submitting a data
file that was really C code and then blindly including code in
prog.c.</p>
file that was really C code and then blindly including code in prog.c.</p>
<p>Quite a few entries suffered from undefined behavior like accessing
uninitialized locals and/or reading-writing below the stack. We advise
running your entry through valgrind to make sure those mistakes are
avoided.</p>
<p>Using extra arguments to <code>main</code>, or arguments of wrong
types as a quick and dirty way of declaring variables is now passé.
Clang, for example, rejects them outright.</p>
uninitialized locals and/or reading-writing below the stack.
We advise running your entry through valgrind to make sure those mistakes
are avoided.</p>
<p>Using extra arguments to <code>main</code>, or arguments of wrong types as a quick and dirty
way of declaring variables is now passé. Clang, for example, rejects them outright.</p>
<p>We hope the authors of some of those entries will fix and re-submit
them for the next IOCCC.</p>
<p>Some entries seemed to have a good idea, but the implementation of
the idea was limited in scope.</p>
<h2 id="final-comments">Final Comments</h2>
<p><strong>IMPORTANT NOTE</strong>: See <a
href="../contact.html">contact.html</a> for up to date contact details
as well as details on how to provide fixes to any of the entries. See
also <a href="../faq.html">the IOCCC FAQ</a> for addition information on
the IOCCC.</p>
<p><strong>IMPORTANT NOTE</strong>: See <a href="../contact.html">contact.html</a> for up to date contact details
as well as details on how to provide fixes to any of the entries.
See also <a href="../faq.html">the IOCCC FAQ</a> for addition information on the IOCCC.</p>
<h1 id="copyright-and-license">Copyright and License</h1>
<p>Copyright (c) 2019,2023, Landon Curt Noll and Leonid A. Broukhis. All
Rights Reserved. This work is licensed under a <a
href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons
CC BY-SA 4.0 DEED Attribution-ShareAlike 4.0 International</a> license.
If you do use this work in some form, the <a href="../judges.html">IOCCC
judges</a> would appreciate (but does not require) if you were to <a
href="../contact.html">send us a note about your use</a>.</p>
<p>Copyright (c) 2019,2023, Landon Curt Noll and Leonid A. Broukhis. All Rights Reserved.
This work is licensed under a <a href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons CC BY-SA 4.0 DEED Attribution-ShareAlike
4.0 International</a> license.
If you do use this work in some form, the <a href="../judges.html">IOCCC judges</a> would appreciate
(but does not require) if you were to <a href="../contact.html">send us a note about your use</a>.</p>
<!-- END: this line ends content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
<!-- START: this line starts content for HTML phase 22 by: bin/output-year-index.sh via bin/md2html.sh -->
<!-- START: this line starts content generated by: bin/output-year-index.sh -->
<h1
id="winning-entries-of-2019---the-26th-ioccc"><a name=inventory></a><a name=2019></a>Winning
Entries of 2019 - The 26th IOCCC</h1>
<p><strong>Download IOCCC</strong> <a
href="2019/ioccc.2019.tar.bz2">2019 entry source</a></p>
<h1 id="winning-entries-of-2019---the-26th-ioccc"><a name=inventory></a><a name=2019></a>Winning Entries of 2019 - The 26th IOCCC</h1>
<p><strong>Download IOCCC</strong> <a href="2019/ioccc.2019.tar.bz2">2019 entry source</a></p>
<ul>
<li><a href="adamovsky/index.html">2019/adamovsky</a> - Most functional
interpreter</li>
<li><a href="adamovsky/index.html">2019/adamovsky</a> - Most functional interpreter</li>
<li><a href="burton/index.html">2019/burton</a> - Best one-liner</li>
<li><a href="ciura/index.html">2019/ciura</a> - Most alphabetic</li>
<li><a href="diels-grabsch1/index.html">2019/diels-grabsch1</a> - Best
small program</li>
<li><a href="diels-grabsch2/index.html">2019/diels-grabsch2</a> - Most
self-aware</li>
<li><a href="dogon/index.html">2019/dogon</a> - Best use of space and
time</li>
<li><a href="duble/index.html">2019/duble</a> - Best collaborative
graphics</li>
<li><a href="endoh/index.html">2019/endoh</a> - Most in need of
debugging</li>
<li><a href="giles/index.html">2019/giles</a> - Most in need of wide
space</li>
<li><a href="karns/index.html">2019/karns</a> - Most in need of
whitespace</li>
<li><a href="lynn/index.html">2019/lynn</a> - Most functional
compiler</li>
<li><a href="mills/index.html">2019/mills</a> - Most in need to be
tweeted</li>
<li><a href="poikola/index.html">2019/poikola</a> - Most
calendrical</li>
<li><a href="yang/index.html">2019/yang</a> - Most in need of
transparency</li>
<li><a href="diels-grabsch1/index.html">2019/diels-grabsch1</a> - Best small program</li>
<li><a href="diels-grabsch2/index.html">2019/diels-grabsch2</a> - Most self-aware</li>
<li><a href="dogon/index.html">2019/dogon</a> - Best use of space and time</li>
<li><a href="duble/index.html">2019/duble</a> - Best collaborative graphics</li>
<li><a href="endoh/index.html">2019/endoh</a> - Most in need of debugging</li>
<li><a href="giles/index.html">2019/giles</a> - Most in need of wide space</li>
<li><a href="karns/index.html">2019/karns</a> - Most in need of whitespace</li>
<li><a href="lynn/index.html">2019/lynn</a> - Most functional compiler</li>
<li><a href="mills/index.html">2019/mills</a> - Most in need to be tweeted</li>
<li><a href="poikola/index.html">2019/poikola</a> - Most calendrical</li>
<li><a href="yang/index.html">2019/yang</a> - Most in need of transparency</li>
</ul>
<p> <strong>Jump to:</strong> <a href="#">top</a></p>
+48 -76
View File
@@ -130,8 +130,8 @@
<h2 id="author"><a name="author"></a>Author:</h2>
<ul>
<li>Name: <a href="../../authors.html#Joshua_Karns">Joshua Karns</a><br>
Location: <a href="../../location.html#US">US</a> - <em>United States of
America</em> (<em>United States</em>) <br><br></li>
Location: <a href="../../location.html#US">US</a> - <em>United States of America</em> (<em>United States</em>)
<br><br></li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-author.sh -->
@@ -141,51 +141,45 @@ America</em> (<em>United States</em>) <br><br></li>
<h2 id="to-build">To build:</h2>
<div class="sourceCode" id="cb1"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span></span></code></pre></div>
<p>NOTE: we disable the optimiser because this program has problems with
it enabled.</p>
<p>NOTE: we disable the optimiser because this program has problems with it
enabled.</p>
<h3 id="bugs-and-misfeatures">Bugs and (Mis)features:</h3>
<p>The current status of this entry is:</p>
<pre><code>STATUS: INABIAF - please **DO NOT** fix</code></pre>
<p>For more detailed information see <a
href="../../bugs.html#2019_karns">2019 karns bugs</a>.</p>
<p>For more detailed information see <a href="../../bugs.html#2019_karns">2019 karns bugs</a>.</p>
<h2 id="to-use">To use:</h2>
<div class="sourceCode" id="cb3"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> <span class="op">&lt;</span> textfile_that_fits_on_the_screen</span></code></pre></div>
<p>You might want to type:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ex">reset</span></span></code></pre></div>
<p>after running the program to restore the terminal to its previous
state.</p>
<p>after running the program to restore the terminal to its previous state.</p>
<h2 id="try">Try:</h2>
<div class="sourceCode" id="cb5"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./try.sh</span></span></code></pre></div>
<p>If you have more time you might want to try:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> <span class="op">&lt;</span> README.md</span></code></pre></div>
<h2 id="judges-remarks">Judges’ remarks:</h2>
<p>If you typically get lost in mazes, watching this program run might –
or might not, YMMV – 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 <code>make test</code>, make it about 120x40
to be safe, ensuring that you see the <code>@</code> sign as well as the
exclamation mark.</p>
<p>If you typically get lost in mazes, watching this program run might – or might
not, YMMV – 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 <code>make test</code>, make it about 120x40 to be safe, ensuring that you
see the <code>@</code> sign as well as the exclamation mark.</p>
<p>…Oh, and the first <code>M</code> in YMMV stands for “mazing”.</p>
<p>A puzzle for the reader: Can you change the program to consider a
diagonal movement as one step?</p>
<p>A puzzle for the reader: Can you change the program to consider a diagonal
movement as one step?</p>
<h2 id="authors-remarks">Author’s remarks:</h2>
<h3 id="the-program">The Program:</h3>
<p>This program is pretty simple! It performs a <a
href="https://en.wikipedia.org/wiki/Breadth-first_search">breadth first
search</a> on the specified graph. The graph can be any ASCII text file
that has an ‘at’ (<code>@</code>) character, which is going to be the
starting location, and a <code>!</code> 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’t spaces
are not connected with anything.</p>
<p>This program is pretty simple! It performs a <a href="https://en.wikipedia.org/wiki/Breadth-first_search">breadth first
search</a> on the
specified graph. The graph can be any ASCII text file that has an ‘at’ (<code>@</code>)
character, which is going to be the starting location, and a <code>!</code> 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’t spaces are not
connected with anything.</p>
<h3 id="compiling-and-running">Compiling and Running:</h3>
<p>This program usually compiles under both GCC and clang. Build
with:</p>
<p>This program usually compiles under both GCC and clang. Build with:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="va">$(</span><span class="ex">CC</span><span class="va">)</span> <span class="at">-std</span><span class="op">=</span>c99 <span class="at">-o</span> tbfs prog.c</span></code></pre></div>
<p>where <code>$(CC)</code> is cc, gcc, clang, or some other C
compiler.</p>
<p>where <code>$(CC)</code> is cc, gcc, clang, or some other C compiler.</p>
<p>You can then run it with:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="fu">cat</span> <span class="op">&lt;</span>input file<span class="op">&gt;</span> <span class="kw">|</span> <span class="ex">./tbfs</span></span></code></pre></div>
<p>Examples:</p>
@@ -193,72 +187,50 @@ compiler.</p>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="ex">./tbfs</span> <span class="op">&lt;</span> prog.c</span></code></pre></div>
<h3 id="issues">Issues</h3>
<ul>
<li>The program must be ran in a terminal that supports ANSI escape
codes for moving the cursor and changing colors.</li>
<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’t know what memory management there is, if any.</li>
<li>The 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’ve not encountered this myself).</li>
<li>The 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’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>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0
License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights
Reserved. You are free to share and adapt this file under the terms of
this license:</p>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0 License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved.
You are free to share and adapt this file under the terms of this license:</p>
<pre><code>Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)</code></pre>
<p>For more information, see:
https://creativecommons.org/licenses/by-sa/4.0/</p>
<p>For more information, see: https://creativecommons.org/licenses/by-sa/4.0/</p>
<!-- END: this line ends content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
<!-- START: this line starts content for HTML phase 22 by: bin/output-index-inventory.sh via bin/md2html.sh -->
<!-- START: this line starts content generated by: bin/output-index-inventory.sh -->
<h1 id="inventory-for-2019karns"><a name="inventory"></a>Inventory for
2019/karns</h1>
<h1 id="inventory-for-2019karns"><a name="inventory"></a>Inventory for 2019/karns</h1>
<p><a href="#top">Jump to top</a></p>
<h2 id="primary-files">Primary files</h2>
<ul>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/karns/prog.c">prog.c</a>
- entry source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/karns/Makefile">Makefile</a>
- entry Makefile</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/karns/prog.orig.c">prog.orig.c</a>
- original source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/karns/maze">maze</a>
- input maze map</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/karns/try.sh">try.sh</a>
- how to run</li>
<li><a href="2019_karns.tar.bz2">2019_karns.tar.bz2</a> - download entry
source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/karns/prog.c">prog.c</a> - entry source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/karns/Makefile">Makefile</a> - entry Makefile</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/karns/prog.orig.c">prog.orig.c</a> - original source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/karns/maze">maze</a> - input maze map</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/karns/try.sh">try.sh</a> - how to run</li>
<li><a href="2019_karns.tar.bz2">2019_karns.tar.bz2</a> - download entry source</li>
</ul>
<h2 id="secondary-files">Secondary files</h2>
<ul>
<li><a href="index.html">index.html</a> - entry home page</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/karns/.entry.json">.entry.json</a>
- description of entry in JSON</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/karns/.gitignore">.gitignore</a>
- list of files that should not be committed under git</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/karns/.entry.json">.entry.json</a> - description of entry in JSON</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/karns/.gitignore">.gitignore</a> - list of files that should not be committed under git</li>
<li><a href=".path">.path</a> - directory path from top directory</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/karns/README.md">README.md</a>
- markdown source for index.html</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/karns/README.md">README.md</a> - markdown source for index.html</li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-inventory.sh -->
+153 -226
View File
@@ -130,8 +130,8 @@
<h2 id="author"><a name="author"></a>Author:</h2>
<ul>
<li>Name: <a href="../../authors.html#Ben_Lynn">Ben Lynn</a><br>
Location: <a href="../../location.html#US">US</a> - <em>United States of
America</em> (<em>United States</em>) <br><br></li>
Location: <a href="../../location.html#US">US</a> - <em>United States of America</em> (<em>United States</em>)
<br><br></li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-author.sh -->
@@ -144,32 +144,28 @@ America</em> (<em>United States</em>) <br><br></li>
<h3 id="bugs-and-misfeatures">Bugs and (Mis)features:</h3>
<p>The current status of this entry is:</p>
<pre><code>STATUS: INABIAF - please **DO NOT** fix</code></pre>
<p>For more detailed information see <a
href="../../bugs.html#2019_lynn">2019 lynn bugs</a>.</p>
<p>For more detailed information see <a href="../../bugs.html#2019_lynn">2019 lynn bugs</a>.</p>
<h2 id="to-use">To use:</h2>
<div class="sourceCode" id="cb3"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span></span></code></pre></div>
<h2 id="try">Try:</h2>
<div class="sourceCode" id="cb4"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./try.sh</span></span></code></pre></div>
<h2 id="judges-remarks">Judges’ remarks:</h2>
<p>A fully functional compiler. The example prints out the 30th <a
href="https://en.wikipedia.org/wiki/Fibonacci_sequence">Fibonacci
<p>A fully functional compiler. The example prints out the 30th <a href="https://en.wikipedia.org/wiki/Fibonacci_sequence">Fibonacci
number</a>.</p>
<h2 id="authors-remarks">Author’s remarks:</h2>
<h3 id="remarks">Remarks:</h3>
<p>A Haskell compiler. Supports a subset of Haskell more than large
enough to self-host. Like GHC with custom language extensions:</p>
<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
on 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>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 on 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>
<h3 id="building">Building:</h3>
@@ -179,102 +175,82 @@ functions. All functions must be pure.</p></li>
<h4 id="fibonacci-numbers">Fibonacci numbers:</h4>
<p>Test the compiler on <a href="fib.hs">fib.hs</a>:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">(</span><span class="ex">./prog</span> <span class="op">&lt;</span> fib.hs <span class="kw">;</span> <span class="fu">cat</span> prog.c<span class="kw">)</span> <span class="op">&gt;</span> fib.c</span></code></pre></div>
<p>Compiling the output produces a binary that prints the 30th Fibonacci
number.</p>
<p>The file <a href="ghcfib.hs">ghcfib.hs</a> includes <a
href="fib.hs">fib.hs</a> with some glue code, and shows GHC also accepts
our subset of Haskell:</p>
<p>Compiling the output produces a binary that prints the 30th Fibonacci number.</p>
<p>The file <a href="ghcfib.hs">ghcfib.hs</a> includes <a href="fib.hs">fib.hs</a> with some glue code,
and shows GHC also accepts our subset of Haskell:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="ex">ghc</span> ghcfib.hs</span></code></pre></div>
<h4 id="self-hosting-compiler">Self-hosting compiler:</h4>
<p>To avoid spoiling this entry by revealing the original Haskell
source, we instead provide <a href="hint.hs">hint.hs</a>, 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>
<p>To avoid spoiling this entry by revealing the original Haskell source, we
instead provide <a href="hint.hs">hint.hs</a>, 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>
<div class="sourceCode" id="cb8"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">(</span><span class="ex">./prog</span> <span class="op">&lt;</span> hint.hs <span class="kw">;</span> <span class="fu">cat</span> prog.c<span class="kw">)</span> <span class="op">&gt;</span> hint.c</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span> hint</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="ex">./hint</span></span></code></pre></div>
<p>The output program behaves like the compiler itself.</p>
<p>Unlike the original source from which it is derived, GHC fails to
compile <a href="hint.hs">hint.hs</a>. This is because values have been
replaced with their <a
href="https://en.wikipedia.org/wiki/Mogensen-Scott_encoding">Scott
encodings</a> by this stage, which messes up type-checks; we’d need
<code>equirecursive</code> types for it to work.</p>
<p>Unlike the original source from which it is derived, GHC fails to compile
<a href="hint.hs">hint.hs</a>. This is because values have been replaced with their <a href="https://en.wikipedia.org/wiki/Mogensen-Scott_encoding">Scott
encodings</a>
by this stage, which messes up type-checks; we’d need <code>equirecursive</code> types for
it to work.</p>
<h4 id="regexes">Regexes:</h4>
<p>The file <a href="lol.hs">lol.hs</a> contains an adaptation of <a
href="https://www.cs.dartmouth.edu/~doug/nfa.pdf">Doug McIlroy’s elegant
code from “Enumerating the strings of regular languages”</a>. We
exercise it by showing the first entries of the length-ordered list of
all strings consisting of the characters <code>a</code> and
<code>b</code> that contain an even number of <code>a</code>s.</p>
<p>The file <a href="lol.hs">lol.hs</a> contains an adaptation of <a href="https://www.cs.dartmouth.edu/~doug/nfa.pdf">Doug McIlroy’s elegant code from
“Enumerating the strings of regular
languages”</a>. We exercise it by
showing the first entries of the length-ordered list of all strings consisting
of the characters <code>a</code> and <code>b</code> that contain an even number of <code>a</code>s.</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">(</span><span class="ex">./prog</span> <span class="op">&lt;</span> lol.hs <span class="kw">;</span> <span class="fu">cat</span> prog.c<span class="kw">)</span> <span class="op">&gt;</span> lol.c</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span> lol</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="ex">./lol</span></span></code></pre></div>
<p>A GHC wrapper is provided:</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ex">ghc</span> ghclol.hs</span></code></pre></div>
<h3 id="strongly-connected-components">Strongly-connected
components:</h3>
<p>See <a href="scc.hs">scc.hs</a> (and its GHC wrapper <a
href="ghcscc.hs">ghcscc.hs</a>) for an elegant way to print the
strongly-connected components of a graph in reverse topological
<div class="sourceCode" id="cb10"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ex">ghc</span> ghclol.hs</span></code></pre></div>
<h3 id="strongly-connected-components">Strongly-connected components:</h3>
<p>See <a href="scc.hs">scc.hs</a> (and its GHC wrapper <a href="ghcscc.hs">ghcscc.hs</a>) for an elegant
way to print the strongly-connected components of a graph in reverse topological
order.</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">(</span><span class="ex">./prog</span> <span class="op">&lt;</span> scc.hs <span class="kw">;</span> <span class="fu">cat</span> prog.c<span class="kw">)</span> <span class="op">&gt;</span> scc.c</span></code></pre></div>
<div class="sourceCode" id="cb11"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">(</span><span class="ex">./prog</span> <span class="op">&lt;</span> scc.hs <span class="kw">;</span> <span class="fu">cat</span> prog.c<span class="kw">)</span> <span class="op">&gt;</span> scc.c</span></code></pre></div>
<p>It expects the input to be in a similar format as a previous entry
(2018 vokes). For example:</p>
<div class="sourceCode" id="cb12"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span> scc</span>
<div class="sourceCode" id="cb12"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span> scc</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="ex">./scc</span> <span class="op">&lt;</span> example-1.txt</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a><span class="ex">./scc</span> <span class="op">&lt;</span> example-2.txt</span></code></pre></div>
<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 non-space character in a vertex
name.)</p>
<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 non-space character in a vertex name.)</p>
<h3 id="syntax">Syntax</h3>
<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>
<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
<code>unsigned int</code>s, and <code>(:)</code> is Haskell’s
<code>cons</code> function. Like Haskell and unlike C,
<code>(&lt;=)</code> returns a <code>Bool</code> (which are Church
booleans behind the scenes) and not an <code>Int</code>.</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>The arithmetic operations behave as they do in C on <code>unsigned int</code>s, and <code>(:)</code> is
Haskell’s <code>cons</code> function. Like Haskell and unlike C, <code>(&lt;=)</code> returns a <code>Bool</code>
(which are Church booleans behind the scenes) and not an <code>Int</code>.</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>
<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>
<h3 id="caveats">Caveats</h3>
<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 <code>identity</code> 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>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
<code>identity</code> 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><code>Bool</code> 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 <code>case</code> expressions must list every
data constructor in the order they are defined. For example, if we
have:</p>
<p>so that it matches the Scott-encoded booleans internally used by the primitive
function <code>(&lt;=)</code>.</p>
<p>The alternatives in a <code>case</code> 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 <code>case</code> expression that examines a term of this type
must have the form:</p>
<p>then a <code>case</code> expression that examines a term of this type must have the form:</p>
<pre><code>case x of
{ Bar a -&gt; ...
; Baz -&gt; ...
@@ -282,169 +258,120 @@ must have the form:</p>
}</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
<code>case</code> alternatives.</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 <code>case</code> alternatives.</p>
<h3 id="why">Why?</h3>
<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>
<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>
<h3 id="obfuscation-techniques">Obfuscation techniques:</h3>
<p>Even with Kiselyov’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>
<p>Even with Kiselyov’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>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 entry (<a
href="../../2018/bellard/index.html">2018/bellard</a>), 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’s jump table for lazy reduction.
A previous entry (<a
href="../../2013/endoh1/index.html">2013/endoh1</a>) has a cuter
solution, which I avoid because of originality concerns and also because
my combinators are compressed.</li>
<li>Mixed radix encoding to game iocccsize. From a past entry
(<a href="../../2018/bellard/index.html">2018/bellard</a>), 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’s jump table for lazy reduction. A previous
entry (<a href="../../2013/endoh1/index.html">2013/endoh1</a>) 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
<code>int</code>s (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, “The Reduceron reconfigured and re-evaluated”</a>. We
represent the integer <code>n</code> with a term equivalent to
<code>Y(BT)n</code>; it works because
<li>Cheaper and more complicated to print comma-separated <code>int</code>s (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,
“The Reduceron reconfigured and
re-evaluated”</a>. We
represent the integer <code>n</code> 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>
<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 <a href="hint.hs">hint.hs</a>.</p>
<p>Other obfuscation techniques are better appreciated after decoding the
compiler. See <a href="hint.hs">hint.hs</a>.</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,
<code>union</code>s may have extra fields, and they’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’s law, which makes some comparisons
less comprehensible.</li>
<li><a href="http://okmij.org/ftp/tagless-final/ski.pdf">Kiselyov only
published “λ to SKI, Semantically” last year</a>.</li>
<li>Recursion via the fixpoint (<code>Y</code>) combinator, which is
represented by the variable <code>""</code> 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>
<li>Sum types are oddly ordered and may even contain unused data constructors to
reduce code duplication. (In C terms, <code>union</code>s may have extra fields, and they’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’s law, which
makes some comparisons less comprehensible.</li>
<li><a href="http://okmij.org/ftp/tagless-final/ski.pdf">Kiselyov only published “λ to SKI, Semantically” last
year</a>.</li>
<li>Recursion via the fixpoint (<code>Y</code>) combinator, which is represented by the
variable <code>""</code> 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>
<h3 id="warnings">Warnings:</h3>
<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>
<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>
<h3 id="behind-the-scenes-commentary">Behind-the-scenes commentary:</h3>
<p><a href="https://crypto.stanford.edu/~blynn/compiler/ioccc.html">My
website reveals how this compiler works</a>.</p>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0
License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights
Reserved. You are free to share and adapt this file under the terms of
this license:</p>
<p><a href="https://crypto.stanford.edu/~blynn/compiler/ioccc.html">My website reveals how this compiler
works</a>.</p>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0 License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved.
You are free to share and adapt this file under the terms of this license:</p>
<pre><code>Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)</code></pre>
<p>For more information, see:
https://creativecommons.org/licenses/by-sa/4.0/</p>
<p>For more information, see: https://creativecommons.org/licenses/by-sa/4.0/</p>
<!-- END: this line ends content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
<!-- START: this line starts content for HTML phase 22 by: bin/output-index-inventory.sh via bin/md2html.sh -->
<!-- START: this line starts content generated by: bin/output-index-inventory.sh -->
<h1 id="inventory-for-2019lynn"><a name="inventory"></a>Inventory for
2019/lynn</h1>
<h1 id="inventory-for-2019lynn"><a name="inventory"></a>Inventory for 2019/lynn</h1>
<p><a href="#top">Jump to top</a></p>
<h2 id="primary-files">Primary files</h2>
<ul>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/prog.c">prog.c</a>
- entry source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/Makefile">Makefile</a>
- entry Makefile</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/prog.orig.c">prog.orig.c</a>
- original source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/example-1.txt">example-1.txt</a>
- sample input</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/example-2.txt">example-2.txt</a>
- sample input</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/try.sh">try.sh</a>
- how to run</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/fib.hs">fib.hs</a>
- compiler macros</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/ghcfib.hs">ghcfib.hs</a>
- compiler macros</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/ghclol.hs">ghclol.hs</a>
- compiler macros</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/ghcscc.hs">ghcscc.hs</a>
- compiler macros</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/lol.hs">lol.hs</a>
- compiler macros</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/scc.hs">scc.hs</a>
- compiler macros</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/hint.hs">hint.hs</a>
- spoiler for compiler macros</li>
<li><a href="2019_lynn.tar.bz2">2019_lynn.tar.bz2</a> - download entry
source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/prog.c">prog.c</a> - entry source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/Makefile">Makefile</a> - entry Makefile</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/prog.orig.c">prog.orig.c</a> - original source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/example-1.txt">example-1.txt</a> - sample input</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/example-2.txt">example-2.txt</a> - sample input</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/try.sh">try.sh</a> - how to run</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/fib.hs">fib.hs</a> - compiler macros</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/ghcfib.hs">ghcfib.hs</a> - compiler macros</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/ghclol.hs">ghclol.hs</a> - compiler macros</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/ghcscc.hs">ghcscc.hs</a> - compiler macros</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/lol.hs">lol.hs</a> - compiler macros</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/scc.hs">scc.hs</a> - compiler macros</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/hint.hs">hint.hs</a> - spoiler for compiler macros</li>
<li><a href="2019_lynn.tar.bz2">2019_lynn.tar.bz2</a> - download entry source</li>
</ul>
<h2 id="secondary-files">Secondary files</h2>
<ul>
<li><a href="index.html">index.html</a> - entry home page</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/.entry.json">.entry.json</a>
- description of entry in JSON</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/.gitignore">.gitignore</a>
- list of files that should not be committed under git</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/.entry.json">.entry.json</a> - description of entry in JSON</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/.gitignore">.gitignore</a> - list of files that should not be committed under git</li>
<li><a href=".path">.path</a> - directory path from top directory</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/README.md">README.md</a>
- markdown source for index.html</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/lynn/README.md">README.md</a> - markdown source for index.html</li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-inventory.sh -->
+296 -441
View File
@@ -129,9 +129,9 @@
<h2 id="author"><a name="author"></a>Author:</h2>
<ul>
<li>Name: <a href="../../authors.html#Christopher_Mills">Christopher
Mills</a><br> Location: <a href="../../location.html#US">US</a> -
<em>United States of America</em> (<em>United States</em>) <br><br></li>
<li>Name: <a href="../../authors.html#Christopher_Mills">Christopher Mills</a><br>
Location: <a href="../../location.html#US">US</a> - <em>United States of America</em> (<em>United States</em>)
<br><br></li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-author.sh -->
@@ -144,88 +144,65 @@ Mills</a><br> Location: <a href="../../location.html#US">US</a> -
<h3 id="bugs-and-misfeatures">Bugs and (Mis)features:</h3>
<p>The current status of this entry is:</p>
<pre><code>STATUS: INABIAF - please **DO NOT** fix</code></pre>
<p>For more detailed information see <a
href="../../bugs.html#2019_mills">2019 mills bugs</a>.</p>
<p>For more detailed information see <a href="../../bugs.html#2019_mills">2019 mills bugs</a>.</p>
<h2 id="to-use">To use:</h2>
<div class="sourceCode" id="cb3"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span> cpclean</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="co"># Let this run for about about an hour and then kill it:</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> Shakespeare.txt</span></code></pre></div>
<h2 id="try">Try:</h2>
<div class="sourceCode" id="cb4"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./try.sh</span></span></code></pre></div>
<p>However, as the binary model files used to produce the output are in
an implementation-specific format, your mileage may vary.</p>
<p>However, as the binary model files used to produce the output are in an
implementation-specific format, your mileage may vary.</p>
<h2 id="judges-remarks">Judges’ remarks:</h2>
<p>Can a machine learn?</p>
<p>Some say so.</p>
<p>But can a machine learn to write like Shakespeare? Can it write rules
and guidelines for the IOCCC?</p>
<p>But can a machine learn to write like Shakespeare? Can it write rules and
guidelines for the IOCCC?</p>
<p>You decide. :-)</p>
<h2 id="authors-remarks">Author’s remarks:</h2>
<h3 id="welcome-to-omlet">Welcome to OMLET! 🍳:</h3>
<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> (RNN). OMLET lets you build, train and evaluate <a
href="https://en.wikipedia.org/wiki/Deep_learning">deep neural
networks</a> (DNN). 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 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> (RNN).
OMLET lets you build, train and evaluate <a href="https://en.wikipedia.org/wiki/Deep_learning">deep neural networks</a> (DNN). 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>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>Hyperparameters 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>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>Hyperparameters 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://karpathy.ai">Andrej Karpathy’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’ve
included a small sample dataset to use for training, but you can have
even more fun by downloading some larger datasets:</p>
<p>OMLET is based on <a href="https://karpathy.ai">Andrej Karpathy’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’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’s 2016 campaign speeches</a></li>
<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’s 2016 campaign speeches</a></li>
</ul>
<h3 id="getting-started-with-omlet">Getting started with OMLET</h3>
<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>
<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">Shakespeare</a>
plays. Start by typing</p>
<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">Shakespeare</a> plays. Start by typing</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span></span></code></pre></div>
<p>After it builds, train it using</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> Shakespere.txt</span></code></pre></div>
<p>This will immediately start outputting gibberish to the output,
e.g.</p>
<p>This will immediately start outputting gibberish to the output, e.g.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> Shakespere.txt</span></code></pre></div>
<p>produces:</p>
<pre><code>sins ohennAu
@@ -260,14 +237,13 @@ Vh th no dh foud bobt werw:s Aotnf Fhwi&#39;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’s
not very successful! Between the chunks of gibberish are training
progress reports that look like</p>
<p>The gibberish is the networks attempt to write a play. So far, it’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>
<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,
@@ -293,12 +269,12 @@ rerytund: tich lon hyivetetgor.
VOLUONIA:
He brich nom dove worthan then wise,
T0:13% 2.254926</code></pre>
<p>It’s already started to figure out things about Shakespeare plays –
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>
<p>It’s already started to figure out things about Shakespeare plays – 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.
@@ -333,58 +309,49 @@ 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 – how well it performs on data it hasn’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>
<p>Validation cycles are used to test the network to see if it has learned to
generalize – how well it performs on data it hasn’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>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
<a href="Shakespeare.txt">Shakespeare.txt</a> 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>
<a href="Shakespeare.txt">Shakespeare.txt</a> 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>
<div class="sourceCode" id="cb13"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> Shakespeare.txt cp01_1.970</span></code></pre></div>
<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’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>
<div class="sourceCode" id="cb14"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> <span class="op">&lt;</span> cp55_1.807</span></code></pre></div>
<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 – using the wrong
checkpoint is likely to cause a crash.</p>
<h3 id="experimenting-with-different-networks">Experimenting with
different networks</h3>
<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>
<div class="sourceCode" id="cb13"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> Shakespeare.txt cp01_1.970</span></code></pre></div>
<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’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>
<div class="sourceCode" id="cb14"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> <span class="op">&lt;</span> cp55_1.807</span></code></pre></div>
<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 – using the wrong checkpoint is likely to
cause a crash.</p>
<h3 id="experimenting-with-different-networks">Experimenting with different networks</h3>
<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>
<div class="sourceCode" id="cb15"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>h <span class="op">=</span> tanh<span class="op">(</span>Wxh <span class="op">*</span> x <span class="op">+</span> Whh <span class="op">*</span> h<span class="ch">&#39; </span><span class="er">+ Bh)</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>y <span class="op">=</span> Why <span class="op">*</span> h <span class="op">+</span> By</span></code></pre></div>
<p>where</p>
@@ -393,36 +360,24 @@ simplest recurrent neural network. It looks like</p>
<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>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(3)</code> is the <a
href="https://en.wikipedia.org/wiki/Hyperbolic_function">hyperbolic
tangent function</a></li>
<li><code>tanh(3)</code> is the <a href="https://en.wikipedia.org/wiki/Hyperbolic_function">hyperbolic tangent function</a></li>
</ul>
<p>The <code>W</code>’s and <code>B</code>’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>The <code>W</code>’s and <code>B</code>’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
“remember” the past. We can see what would happen if we removed this
hidden state. If you type</p>
<div class="sourceCode" id="cb16"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span> lin1</span></code></pre></div>
<p>OMLET will create an <a
href="https://en.wikipedia.org/wiki/ADALINE">ADALINE</a> network that
does</p>
“remember” the past. We can see what would happen if we removed this hidden
state. If you type</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span> lin1</span></code></pre></div>
<p>OMLET will create an <a href="https://en.wikipedia.org/wiki/ADALINE">ADALINE</a> network that does</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>y <span class="op">=</span> Wxy <span class="op">*</span> x <span class="op">+</span> By</span></code></pre></div>
<p>This is a 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>
<div class="sourceCode" id="cb18"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./lin1</span> Shakespeare.txt</span></code></pre></div>
<p>The linear network won’t be able to get past the gibberish stage,
because it lacks history:</p>
<div class="sourceCode" id="cb19"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./lin1</span> Shakespeare.txt</span></code></pre></div>
<p>This is a 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>
<div class="sourceCode" id="cb18"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./lin1</span> Shakespeare.txt</span></code></pre></div>
<p>The linear network won’t be able to get past the gibberish stage, because it
lacks history:</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./lin1</span> Shakespeare.txt</span></code></pre></div>
<p>produces:</p>
<pre><code>UERond w,
@@ -446,92 +401,68 @@ I&#39;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(3)</code>
function in the RNN. <code>tanh(3)</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>
<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(3)</code> function in the RNN.
<code>tanh(3)</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’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> - note that’s not
<code>perl</code> the language but <code>per</code> with the digit
1).</p>
nonlinearity, all of the linear functions would fold together into a single
matrix-vector multiply and you’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> - note that’s not <code>perl</code>
the language but <code>per</code> with the digit 1).</p>
<h3 id="going-deeper">Going deeper:</h3>
<p>We can try to improve the RNN’s performance by stacking RNN modules
atop each other:</p>
<p>We can try to improve the RNN’s performance by stacking RNN modules atop each
other:</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a>h1 <span class="op">=</span> RNN<span class="op">(</span>h1<span class="ch">&#39;,</span><span class="er"> x)</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>h2 <span class="op">=</span> RNN<span class="op">(</span>h2<span class="ch">&#39;,</span><span class="er"> h1)</span></span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>y <span class="op">=</span> Why <span class="op">*</span> h2 <span class="op">+</span> By</span></code></pre></div>
<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’s performance, at the cost of a much larger parameter
space.</p>
<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’s
performance, at the cost of a much larger parameter space.</p>
<hr />
<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’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>
<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’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>
<hr />
<p>You can try the deeper network by doing</p>
<div class="sourceCode" id="cb22"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span> rnn2</span></code></pre></div>
<p>(or even <code>make rnn3</code> if you want a three-layer RNN) and
train it with</p>
<div class="sourceCode" id="cb23"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./rnn2</span> Shakespeare.txt</span></code></pre></div>
<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 -- 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>
<div class="sourceCode" id="cb22"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span> rnn2</span></code></pre></div>
<p>(or even <code>make rnn3</code> if you want a three-layer RNN) and train it with</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./rnn2</span> Shakespeare.txt</span></code></pre></div>
<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
-- 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>
<h3 id="lstms-and-grus">LSTMs and GRUs</h3>
<p>RNNs are particularly hard to train because they are trained using <a
href="https://en.wikipedia.org/wiki/Backpropagation_through_time">backpropagation
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>
<div class="sourceCode" id="cb24"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span> lstm2</span></code></pre></div>
<p>RNNs are particularly hard to train because they are trained using
<a href="https://en.wikipedia.org/wiki/Backpropagation_through_time">backpropagation 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>
<div class="sourceCode" id="cb24"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span> lstm2</span></code></pre></div>
<p>and train with it with</p>
<div class="sourceCode" id="cb25"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./lstm2</span> Shakespeare.txt</span></code></pre></div>
<p>The LSTM is much easier to train because it explicitly decides how to
update its hidden state via “gates”. These gates are called</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./lstm2</span> Shakespeare.txt</span></code></pre></div>
<p>The LSTM is much easier to train because it explicitly decides how to update
its hidden state via “gates”. 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>
<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>
<div class="sourceCode" id="cb26"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a>f <span class="op">=</span> sigmoid<span class="op">(</span>Wxf <span class="op">*</span> x <span class="op">+</span> Whf <span class="op">*</span> h<span class="ch">&#39; </span><span class="er">+ Bf)</span></span>
@@ -542,95 +473,70 @@ used to produce the output</li>
<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
“memory” of the LSTM</li>
<li><code>h'</code> and <code>c'</code> 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>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 “memory” of the LSTM</li>
<li><code>h'</code> and <code>c'</code> 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(3)</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>
<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’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>
<div class="sourceCode" id="cb27"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span> gru2</span></code></pre></div>
<p>There are several LSTM variants (see <a href="http://colah.github.io/posts/2015-08-Understanding-LSTMs/">C. Olah’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>
<div class="sourceCode" id="cb27"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span> gru2</span></code></pre></div>
<h3 id="building-your-own-networks">Building your own networks</h3>
<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’t the limit of
OMLET’s power – you can create your own networks by modifying the
<code>Makefile</code>. Networks are passed in on the compiler’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>
<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’t the limit of OMLET’s power – you can create your
own networks by modifying the <code>Makefile</code>. Networks are passed in on the
compiler’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 class="make"><code>-DNW=&#39; x = I(n), hp = I(128), \
h = C(hp, T(A(L(128, x), L(128, hp)))), \
y = L(n, h)&#39;</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 – 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 – 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(3)</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>
<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 – 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 – 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(3)</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 class="make"><code>-DHS=128, \
-DNW=&#39; x = I(n), \
y = L(n, MD(MD(x)))&#39; \
@@ -641,167 +547,116 @@ two-layer GRU network:</p>
zc = OG(1, -1, z), \
h = C(hp, A(M(zc, hp), M(z, c))), \
y = h&#39;</code></pre>
<p>We are using a few new tricks here – first, we are defining
<code>HS</code> as the size of the hidden and cell vectors. There’s
nothing special about this name, it’s just convenient to specify it so
we don’t have a bunch of constants in the code. Second, the network
itself is very simple – 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… 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’s
linear interpolator.</p>
<p>We are using a few new tricks here – first, we are defining <code>HS</code> as the size
of the hidden and cell vectors. There’s nothing special about this name, it’s
just convenient to specify it so we don’t have a bunch of constants in the
code. Second, the network itself is very simple – 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… 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’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>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>
<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’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>
<p>Note: even if you don’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>
<h3 id="hyperparameters">Hyperparameters</h3>
<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>
<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><code>N</code>: 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)">regularization</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>
<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><code>N</code>: 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)">regularization</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>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0
License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights
Reserved. You are free to share and adapt this file under the terms of
this license:</p>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0 License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved.
You are free to share and adapt this file under the terms of this license:</p>
<pre><code>Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)</code></pre>
<p>For more information, see:
https://creativecommons.org/licenses/by-sa/4.0/</p>
<p>For more information, see: https://creativecommons.org/licenses/by-sa/4.0/</p>
<!-- END: this line ends content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
<!-- START: this line starts content for HTML phase 22 by: bin/output-index-inventory.sh via bin/md2html.sh -->
<!-- START: this line starts content generated by: bin/output-index-inventory.sh -->
<h1 id="inventory-for-2019mills"><a name="inventory"></a>Inventory for
2019/mills</h1>
<h1 id="inventory-for-2019mills"><a name="inventory"></a>Inventory for 2019/mills</h1>
<p><a href="#top">Jump to top</a></p>
<h2 id="primary-files">Primary files</h2>
<ul>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/mills/prog.c">prog.c</a>
- entry source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/mills/Makefile">Makefile</a>
- entry Makefile</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/mills/prog.orig.c">prog.orig.c</a>
- original source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/mills/try.sh">try.sh</a>
- how to run</li>
<li><a href="2019_mills.tar.bz2">2019_mills.tar.bz2</a> - download entry
source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/mills/prog.c">prog.c</a> - entry source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/mills/Makefile">Makefile</a> - entry Makefile</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/mills/prog.orig.c">prog.orig.c</a> - original source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/mills/try.sh">try.sh</a> - how to run</li>
<li><a href="2019_mills.tar.bz2">2019_mills.tar.bz2</a> - download entry source</li>
</ul>
<h2 id="secondary-files">Secondary files</h2>
<ul>
<li><a href="index.html">index.html</a> - entry home page</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/mills/.entry.json">.entry.json</a>
- description of entry in JSON</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/mills/.gitignore">.gitignore</a>
- list of files that should not be committed under git</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/mills/.entry.json">.entry.json</a> - description of entry in JSON</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/mills/.gitignore">.gitignore</a> - list of files that should not be committed under git</li>
<li><a href=".path">.path</a> - directory path from top directory</li>
<li><a href="Eugene_Onegin.cp11_1.188">Eugene_Onegin.cp11_1.188</a> -
training data from Eugene Onegin poetry</li>
<li><a href="Eugene_Onegin.txt.gz">Eugene_Onegin.txt.gz</a> - compressed
Eugene Onegin poetry</li>
<li><a
href="IOCCC-Rules-Guidelines.cp98_0.175">IOCCC-Rules-Guidelines.cp98_0.175</a>
- training data from IOCCC 1984-2019 rules guidelines</li>
<li><a
href="IOCCC-Rules-Guidelines.txt.gz">IOCCC-Rules-Guidelines.txt.gz</a> -
compressed IOCCC rules and guidelines 1984-2019</li>
<li><a href="IOCCC-hints.cp09_1.809">IOCCC-hints.cp09_1.809</a> -
training data from IOCCC hints file text for 1984-2018</li>
<li><a href="IOCCC-hints.txt.gz">IOCCC-hints.txt.gz</a> - compressed
IOCCC hints for 1984-2018</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/mills/README.md">README.md</a>
- markdown source for index.html</li>
<li><a href="Shakespeare.cp04_1.633">Shakespeare.cp04_1.633</a> -
training data from Shakespeare text</li>
<li><a href="Shakespeare.txt.gz">Shakespeare.txt.gz</a> - compressed
Shakespeare text</li>
<li><a href="Eugene_Onegin.cp11_1.188">Eugene_Onegin.cp11_1.188</a> - training data from Eugene Onegin poetry</li>
<li><a href="Eugene_Onegin.txt.gz">Eugene_Onegin.txt.gz</a> - compressed Eugene Onegin poetry</li>
<li><a href="IOCCC-Rules-Guidelines.cp98_0.175">IOCCC-Rules-Guidelines.cp98_0.175</a> - training data from IOCCC 1984-2019 rules guidelines</li>
<li><a href="IOCCC-Rules-Guidelines.txt.gz">IOCCC-Rules-Guidelines.txt.gz</a> - compressed IOCCC rules and guidelines 1984-2019</li>
<li><a href="IOCCC-hints.cp09_1.809">IOCCC-hints.cp09_1.809</a> - training data from IOCCC hints file text for 1984-2018</li>
<li><a href="IOCCC-hints.txt.gz">IOCCC-hints.txt.gz</a> - compressed IOCCC hints for 1984-2018</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/mills/README.md">README.md</a> - markdown source for index.html</li>
<li><a href="Shakespeare.cp04_1.633">Shakespeare.cp04_1.633</a> - training data from Shakespeare text</li>
<li><a href="Shakespeare.txt.gz">Shakespeare.txt.gz</a> - compressed Shakespeare text</li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-inventory.sh -->
+142 -207
View File
@@ -130,8 +130,8 @@
<h2 id="author"><a name="author"></a>Author:</h2>
<ul>
<li>Name: <a href="../../authors.html#Timo_Poikola">Timo Poikola</a><br>
Location: <a href="../../location.html#FI">FI</a> - <em>Republic of
Finland </em> (<em>Finland</em>) <br><br></li>
Location: <a href="../../location.html#FI">FI</a> - <em>Republic of Finland </em> (<em>Finland</em>)
<br><br></li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-author.sh -->
@@ -141,18 +141,16 @@ Finland </em> (<em>Finland</em>) <br><br></li>
<h2 id="to-build">To build:</h2>
<div class="sourceCode" id="cb1"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span></span></code></pre></div>
<p>There is an alternate version of this program which changes the way
the output is displayed. See <a href="#alternate-code">Alternate
code</a> below.</p>
<p>NOTE: we disable the optimiser because the author stated that for GCC
optimiser level 0 gave correct output. With clang [0123s] works which
suggests that [123s] might or might not work with GCC. Likewise, we do
similar for the standard, forcing <code>-std=gnu11</code>.</p>
<p>There is an alternate version of this program which changes the way the output
is displayed. See <a href="#alternate-code">Alternate code</a> below.</p>
<p>NOTE: we disable the optimiser because the author stated that for GCC optimiser
level 0 gave correct output. With clang [0123s] works which suggests that [123s]
might or might not work with GCC. Likewise, we do similar for the standard,
forcing <code>-std=gnu11</code>.</p>
<h3 id="bugs-and-misfeatures">Bugs and (Mis)features:</h3>
<p>The current status of this entry is:</p>
<pre><code>STATUS: INABIAF - please **DO NOT** fix</code></pre>
<p>For more detailed information see <a
href="../../bugs.html#2019_poikola">2019 poikola bugs</a>.</p>
<p>For more detailed information see <a href="../../bugs.html#2019_poikola">2019 poikola bugs</a>.</p>
<h2 id="to-use">To use:</h2>
<div class="sourceCode" id="cb3"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> 512 ./prog</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a></span>
@@ -163,17 +161,15 @@ href="../../bugs.html#2019_poikola">2019 poikola bugs</a>.</p>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> 512 ./prog</span></code></pre></div>
<p>If you wish for some documentation:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span> docs</span></code></pre></div>
<p>This will create the file <code>poikola.pdf</code> for your
enjoyment.</p>
<p>This will create the file <code>poikola.pdf</code> for your enjoyment.</p>
<h2 id="try">Try:</h2>
<p>If you don’t have a few days, try:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./try.sh</span></span></code></pre></div>
<p>As the <a href="../../bugs.html#2019_poikola">2019 poikola bugs</a>
says, this program will not validate input so it might get stuck or fail
if invoked erroneously.</p>
<p>As the <a href="../../bugs.html#2019_poikola">2019 poikola bugs</a> says, this program will not validate
input so it might get stuck or fail if invoked erroneously.</p>
<h2 id="alternate-code">Alternate code:</h2>
<p>This version prints a newline after each number for parsing in other
ways than what can be done with the original entry.</p>
<p>This version prints a newline after each number for parsing in other ways than
what can be done with the original entry.</p>
<h3 id="alternate-build">Alternate build:</h3>
<div class="sourceCode" id="cb6"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span> alt</span></code></pre></div>
<h3 id="alternate-use">Alternate use:</h3>
@@ -181,19 +177,16 @@ ways than what can be done with the original entry.</p>
<h3 id="alternate-try">Alternate try:</h3>
<div class="sourceCode" id="cb7"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./try.alt.sh</span></span></code></pre></div>
<h2 id="judges-remarks">Judges’ remarks:</h2>
<p>Do you have the time to see what this program does? Think again, come
back and try again.</p>
<p>Note that <a href="https://t5k.org/curios/page.php/2.html">2</a> can
be said to be the least <a
href="https://en.wikipedia.org/wiki/Parity_(mathematics)">odd</a> <a
href="https://en.wikipedia.org/wiki/Prime_number">prime</a> because it
is the greatest <a
href="https://en.wikipedia.org/wiki/Parity_(mathematics)">even</a>
prime. Moreover <code>2</code> 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
<p>Do you have the time to see what this program does? Think again, come back and
try again.</p>
<p>Note that <a href="https://t5k.org/curios/page.php/2.html">2</a> can be said to be the
least <a href="https://en.wikipedia.org/wiki/Parity_(mathematics)">odd</a>
<a href="https://en.wikipedia.org/wiki/Prime_number">prime</a> because it is the greatest
<a href="https://en.wikipedia.org/wiki/Parity_(mathematics)">even</a> prime. Moreover <code>2</code>
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änen</a>.</p>
<h2 id="authors-remarks">Author’s remarks:</h2>
<h3 id="how-to-build">How to build:</h3>
@@ -201,215 +194,157 @@ Nykänen</a>.</p>
<p>or</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="fu">clang</span> <span class="at">-O</span><span class="pp">[</span><span class="ss">0123s</span><span class="pp">]</span> <span class="at">-o</span> prog prog.c</span></code></pre></div>
<p>e.g.:</p>
<div class="sourceCode" id="cb10"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="fu">clang</span> <span class="at">-O1</span> <span class="at">-o</span> prog prog.c</span></code></pre></div>
<div class="sourceCode" id="cb10"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="fu">clang</span> <span class="at">-O1</span> <span class="at">-o</span> prog prog.c</span></code></pre></div>
<h3 id="poster">Poster:</h3>
<p>You can generate an A3 sized poster by <code>make docs</code>. This
command creates a pdf file <code>poikola.pdf</code>. This requires the
<p>You can generate an A3 sized poster by <code>make docs</code>. This command creates a pdf
file <code>poikola.pdf</code>. This requires the
<a href="https://en.wikipedia.org/wiki/PdfTeX">pdfTeX</a> tool.</p>
<h3 id="what-this-entry-does">What this entry does:</h3>
<p>An old wise man mumbled to me: &gt; Implement a program, which can
calculate SHA-3 checksum for a file –</p>
<p>An old wise man mumbled to me:
&gt; Implement a program, which can calculate SHA-3 checksum for a file –</p>
<p>I thought it was easy, but the wizard didn’t stop yet:</p>
<blockquote>
<p>and primes and Fibonacci numbers.</p>
</blockquote>
<p>Still easy. But the <a
href="https://www.glyphweb.com/arda/g/gandalf.html">Gandalf the Grey</a>
impersonator was not ready:</p>
<p>Still easy. But the <a href="https://www.glyphweb.com/arda/g/gandalf.html">Gandalf the
Grey</a> impersonator was not ready:</p>
<blockquote>
<p>But use only <code>main()</code>, and do not use <code>math.h</code>
nor predefined stuff at all. But wait, there are more rules: This work
should reflect the extraordinary mind of Matti Nykä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>
<p>But use only <code>main()</code>, and do not use <code>math.h</code> nor predefined stuff at all.
But wait, there are more rules: This work should reflect the extraordinary mind
of Matti Nykä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>
<h3 id="oh-boys">Oh boys:</h3>
<p>So, I followed the rules given by <a
href="https://www.glyphweb.com/arda/g/gandalf.html">Gandalf the
White</a> and the <a href="../../judges.html">Judges of the
IOCCC</a>.</p>
<p>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 <a href="https://en.wikipedia.org/wiki/Tripundra">tripundra</a>, 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:</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> <span class="op">&lt;</span>integer<span class="op">&gt;</span> <span class="op">&lt;</span>file<span class="op">&gt;</span></span></code></pre></div>
<p>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 <a
href="https://en.wikipedia.org/wiki/Fibonacci_sequence">Fibonacci
sequence</a> or <a
href="https://en.wikipedia.org/wiki/Prime_number">prime numbers</a>.
<em>Please note that maximum file size is one gigabyte</em>!</p>
<p>So, I followed the rules given by <a href="https://www.glyphweb.com/arda/g/gandalf.html">Gandalf the
White</a> and the <a href="../../judges.html">Judges of
the IOCCC</a>.</p>
<p>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
<a href="https://en.wikipedia.org/wiki/Tripundra">tripundra</a>, 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:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> <span class="op">&lt;</span>integer<span class="op">&gt;</span> <span class="op">&lt;</span>file<span class="op">&gt;</span></span></code></pre></div>
<p>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
<a href="https://en.wikipedia.org/wiki/Fibonacci_sequence">Fibonacci sequence</a> or <a href="https://en.wikipedia.org/wiki/Prime_number">prime
numbers</a>. <em>Please note that maximum
file size is one gigabyte</em>!</p>
<h3 id="obfuscation">Obfuscation:</h3>
<p><em>Matti Nykänen</em>: Every time I jump, and I get that feeling of
<em>bon voyage</em>, the feeling that I’ve been here before.</p>
<p><em>Matti Nykänen</em>: When you are about to jump, you are all alone
and have to make your own decisions. Up there, it’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(3)</code>. Some Finnish <a
href="https://en.wikipedia.org/wiki/Ski_jumping">ski jumping</a> sites
are used as labels, however, there is <code>lahti</code> instead of
<tt style="font-family: Monaco,
<p><em>Matti Nykänen</em>: Every time I jump, and I get that feeling of <em>bon voyage</em>,
the feeling that I’ve been here before.</p>
<p><em>Matti Nykänen</em>: When you are about to jump, you are all alone and have to
make your own decisions. Up there, it’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(3)</code>. Some
Finnish <a href="https://en.wikipedia.org/wiki/Ski_jumping">ski jumping</a> 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ä</tt>.</p>
<h3 id="sha-3-512-compatibility-chart">SHA-3-512 Compatibility
chart</h3>
<p>Tested against <a
href="https://www.di-mgt.com.au/sha_testvectors.html">test
vectors</a>.</p>
<p>Clang-4.0: For optimization levels [0123s], the program compiles and
produces correct output for every tested vector using the C standards
c11, c89, c90, c99, gnu11, gnu1x, gnu89, gnu90, gnu99, iso9899:1990,
iso9899:199409, iso9899:1999 and iso9899:2011 (argument of
<code>-std=</code>).</p>
<h3 id="sha-3-512-compatibility-chart">SHA-3-512 Compatibility chart</h3>
<p>Tested against <a href="https://www.di-mgt.com.au/sha_testvectors.html">test vectors</a>.</p>
<p>Clang-4.0: For optimization levels [0123s], the program compiles and produces
correct output for every tested vector using the C standards c11, c89, c90, c99,
gnu11, gnu1x, gnu89, gnu90, gnu99, iso9899:1990, iso9899:199409, iso9899:1999
and iso9899:2011 (argument of <code>-std=</code>).</p>
<p>GCC-6: For optimization level 0, correct output using the C standards
c11, c99, gnu11, gnu1x, gnu89, gnu90, gnu99, iso9899:1999 and
iso9899:2011.</p>
c11, c99, gnu11, gnu1x, gnu89, gnu90, gnu99, iso9899:1999 and iso9899:2011.</p>
<h3 id="missing-a-prime">Missing a prime</h3>
<p>For obvious reason, the <a
href="https://mathworld.wolfram.com/OddPrime.html">oddest prime</a> is
missing from output.</p>
<p>For obvious reason, the <a href="https://mathworld.wolfram.com/OddPrime.html">oddest
prime</a> is missing from output.</p>
<h3 id="observations">Observations</h3>
<p><code>gcc</code> and <code>clang</code> 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>
<p><code>gcc</code> and <code>clang</code> 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 id="major-spoilers">Major spoilers</h3>
<p>It is commonly believed that <a
href="http://www.cadaeic.net/calendar.htm">Mike Keith’s algorithm</a>
published in <em>Journal of Recreational Mathematics</em>, Vol. 22,
No. 4, 1990, p. 280, is the shortest way to calculate the day of the
week for a given date.</p>
<p>It is commonly believed that <a href="http://www.cadaeic.net/calendar.htm">Mike Keith’s
algorithm</a> published in <em>Journal of
Recreational Mathematics</em>, Vol. 22, No. 4, 1990, p. 280, is the shortest way to
calculate the day of the week for a given date.</p>
<h4 id="keiths-versus-my-algorithm">Keith’s versus my algorithm</h4>
<p>Kieth’s algorithm is
<code>(d+=m&lt;3?y--:y-2,23*m/9+d+4+y/4-y/100+y/400)%7</code>. I noticed
that <code>(23*m/9+(m&lt;3?y--:y-2)+d+4+y/4-y/100+y/400)%7</code> is one
character shorter. In my solution, <code>m&lt;3?y--:y-2</code> is used
directly, instead of assigning a value to <code>d</code>.</p>
<p><code>Q</code> is pronounced in Finnish exactly like
<code>kuu</code>, a word for <a
href="https://en.wikipedia.org/wiki/Month">month</a> or the <a
href="https://en.wikipedia.org/wiki/Moon">Moon</a>. So,
<code>Q = k</code> is intended.</p>
<p>Last term of outputted <a
href="https://en.wikipedia.org/wiki/Fibonacci_sequence">Fibonacci
sequence</a> is the last one smaller than 2<sup>64</sup>. It is a plain
but funny coincidence that the value of <code>^</code> is 94 in <a
href="https://en.wikipedia.org/wiki/ASCII">ASCII</a>.</p>
<p>For <a href="https://en.wikipedia.org/wiki/Prime_number">prime
calculations</a>: 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>
<p>Kieth’s algorithm is <code>(d+=m&lt;3?y--:y-2,23*m/9+d+4+y/4-y/100+y/400)%7</code>. I noticed
that <code>(23*m/9+(m&lt;3?y--:y-2)+d+4+y/4-y/100+y/400)%7</code> is one character shorter. In
my solution, <code>m&lt;3?y--:y-2</code> is used directly, instead of assigning a value to
<code>d</code>.</p>
<p><code>Q</code> is pronounced in Finnish exactly like <code>kuu</code>, a word for
<a href="https://en.wikipedia.org/wiki/Month">month</a> or the
<a href="https://en.wikipedia.org/wiki/Moon">Moon</a>. So, <code>Q = k</code> is intended.</p>
<p>Last term of outputted <a href="https://en.wikipedia.org/wiki/Fibonacci_sequence">Fibonacci
sequence</a> is the last one
smaller than 2<sup>64</sup>. It is a plain but funny coincidence
that the value of <code>^</code> is 94 in <a href="https://en.wikipedia.org/wiki/ASCII">ASCII</a>.</p>
<p>For <a href="https://en.wikipedia.org/wiki/Prime_number">prime calculations</a>: 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 id="other-stuff">Other stuff</h3>
<p><a href="../../authors.html#Cody_Boone_Ferguson">Cody Boone
Ferguson</a>: 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 <a href="../../judges.html">the Judges</a>, I tried to
write this entry in a different way than <a
href="../../2018/poikola/index.html">Most Stellar</a>, but in this code
there is at least one recycled thing from it. By the way, the answers to
the questions I posed: (1) 255. (2) Try to compare binary
representations of those <code>float</code>s and binary representation
of the string “<code>25th IOCCC!</code>”. (3) I don’t know. I used
standard <a
href="https://en.wikipedia.org/wiki/Trigonometric_functions">trigonometric
functions</a> from <a
href="https://en.wikipedia.org/wiki/C_mathematical_functions#Overview_of_functions">math.h</a>
for rotating the <a href="https://en.wikipedia.org/wiki/Big_Dipper">Big
Dipper</a> 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 <a
href="https://en.wikipedia.org/wiki/Fletcher%27s_checksum#Fletcher-16">Fletcher’s
16 checksum</a> does not match anymore and <code>goto</code> jumps to
the end of the code.</p>
<p>I see that one of the <a
href="../../authors.html#Volker_Diels-Grabsch">Volker
Diels-Grabsch</a>’s winning entries is awarded the category <a
href="../../2019/diels-grabsch2/prog.c">Most self-aware</a>. In last
year, my entry incorporates the <a
href="https://en.wikipedia.org/wiki/Fletcher%27s_checksum#Fletcher-16">Fletcher’s
16 algorithm</a> to ensure integrity of code. One of my first ideas for
this year was to do the same thing, but with <a
href="https://en.wikipedia.org/wiki/SHA-3">SHA-3</a>. Using Fletcher 16,
calculating a <a
href="https://en.wikipedia.org/wiki/Checksum">checksum</a> which matches
with <code>sleeping time factor</code> took about one minute. I realized
that SHA-3 even with 224-<a
href="https://en.wikipedia.org/wiki/Bit">bit</a> output could take too
much <a
href="https://en.wikipedia.org/wiki/Central_processing_unit">CPU</a>
time.</p>
<p>I would like to say <em>thanks</em> to PSP, because there were not
too many interruptions during the coding phase.</p>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0
License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights
Reserved. You are free to share and adapt this file under the terms of
this license:</p>
<p><a href="../../authors.html#Cody_Boone_Ferguson">Cody Boone Ferguson</a>: 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 <a href="../../judges.html">the Judges</a>, I tried to write this
entry in a different way than <a href="../../2018/poikola/index.html">Most Stellar</a>, but in this
code there is at least one recycled thing from it. By the way, the answers to
the questions I posed: (1) 255. (2) Try to compare binary representations of
those <code>float</code>s and binary representation of the string “<code>25th IOCCC!</code>”. (3) I
don’t know. I used standard <a href="https://en.wikipedia.org/wiki/Trigonometric_functions">trigonometric
functions</a> from
<a href="https://en.wikipedia.org/wiki/C_mathematical_functions#Overview_of_functions">math.h</a>
for rotating the <a href="https://en.wikipedia.org/wiki/Big_Dipper">Big Dipper</a> 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 <a href="https://en.wikipedia.org/wiki/Fletcher%27s_checksum#Fletcher-16">Fletcher’s 16
checksum</a> does
not match anymore and <code>goto</code> jumps to the end of the code.</p>
<p>I see that one of the <a href="../../authors.html#Volker_Diels-Grabsch">Volker
Diels-Grabsch</a>’s winning entries is
awarded the category <a href="../../2019/diels-grabsch2/prog.c">Most self-aware</a>. In last
year, my entry incorporates the <a href="https://en.wikipedia.org/wiki/Fletcher%27s_checksum#Fletcher-16">Fletcher’s 16
algorithm</a> to
ensure integrity of code. One of my first ideas for this year was to do the same
thing, but with <a href="https://en.wikipedia.org/wiki/SHA-3">SHA-3</a>. Using Fletcher 16,
calculating a <a href="https://en.wikipedia.org/wiki/Checksum">checksum</a> which matches
with <code>sleeping time factor</code> took about one minute. I realized that SHA-3 even
with 224-<a href="https://en.wikipedia.org/wiki/Bit">bit</a> output could take too much
<a href="https://en.wikipedia.org/wiki/Central_processing_unit">CPU</a> time.</p>
<p>I would like to say <em>thanks</em> to PSP, because there were not too many
interruptions during the coding phase.</p>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0 License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved.
You are free to share and adapt this file under the terms of this license:</p>
<pre><code>Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)</code></pre>
<p>For more information, see:
https://creativecommons.org/licenses/by-sa/4.0/</p>
<p>For more information, see: https://creativecommons.org/licenses/by-sa/4.0/</p>
<!-- END: this line ends content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
<!-- START: this line starts content for HTML phase 22 by: bin/output-index-inventory.sh via bin/md2html.sh -->
<!-- START: this line starts content generated by: bin/output-index-inventory.sh -->
<h1 id="inventory-for-2019poikola"><a name="inventory"></a>Inventory for
2019/poikola</h1>
<h1 id="inventory-for-2019poikola"><a name="inventory"></a>Inventory for 2019/poikola</h1>
<p><a href="#top">Jump to top</a></p>
<h2 id="primary-files">Primary files</h2>
<ul>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/poikola/prog.c">prog.c</a>
- entry source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/poikola/Makefile">Makefile</a>
- entry Makefile</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/poikola/prog.alt.c">prog.alt.c</a>
- alternative source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/poikola/prog.orig.c">prog.orig.c</a>
- original source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/poikola/poikola.tex">poikola.tex</a>
- supplied documentation</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/poikola/try.alt.sh">try.alt.sh</a>
- how to run alternative code</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/poikola/try.sh">try.sh</a>
- how to run</li>
<li><a href="2019_poikola.tar.bz2">2019_poikola.tar.bz2</a> - download
entry source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/poikola/prog.c">prog.c</a> - entry source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/poikola/Makefile">Makefile</a> - entry Makefile</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/poikola/prog.alt.c">prog.alt.c</a> - alternative source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/poikola/prog.orig.c">prog.orig.c</a> - original source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/poikola/poikola.tex">poikola.tex</a> - supplied documentation</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/poikola/try.alt.sh">try.alt.sh</a> - how to run alternative code</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/poikola/try.sh">try.sh</a> - how to run</li>
<li><a href="2019_poikola.tar.bz2">2019_poikola.tar.bz2</a> - download entry source</li>
</ul>
<h2 id="secondary-files">Secondary files</h2>
<ul>
<li><a href="index.html">index.html</a> - entry home page</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/poikola/.entry.json">.entry.json</a>
- description of entry in JSON</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/poikola/.gitignore">.gitignore</a>
- list of files that should not be committed under git</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/poikola/.entry.json">.entry.json</a> - description of entry in JSON</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/poikola/.gitignore">.gitignore</a> - list of files that should not be committed under git</li>
<li><a href=".path">.path</a> - directory path from top directory</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/poikola/README.md">README.md</a>
- markdown source for index.html</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/poikola/README.md">README.md</a> - markdown source for index.html</li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-inventory.sh -->
+76 -115
View File
@@ -130,8 +130,8 @@
<h2 id="author"><a name="author"></a>Author:</h2>
<ul>
<li>Name: <a href="../../authors.html#Don_Yang">Don Yang</a><br>
Location: <a href="../../location.html#US">US</a> - <em>United States of
America</em> (<em>United States</em>) <br><br></li>
Location: <a href="../../location.html#US">US</a> - <em>United States of America</em> (<em>United States</em>)
<br><br></li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-author.sh -->
@@ -144,8 +144,7 @@ America</em> (<em>United States</em>) <br><br></li>
<h3 id="bugs-and-misfeatures">Bugs and (Mis)features:</h3>
<p>The current status of this entry is:</p>
<pre><code>STATUS: INABIAF - please **DO NOT** fix</code></pre>
<p>For more detailed information see <a
href="../../bugs.html#2019_yang">2019 yang bugs</a>.</p>
<p>For more detailed information see <a href="../../bugs.html#2019_yang">2019 yang bugs</a>.</p>
<h2 id="to-use">To use:</h2>
<div class="sourceCode" id="cb3"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> sample_input.txt a b c d</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a></span>
@@ -161,8 +160,8 @@ href="../../bugs.html#2019_yang">2019 yang bugs</a>.</p>
<h2 id="try">Try:</h2>
<div class="sourceCode" id="cb4"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./try.sh</span></span></code></pre></div>
<h2 id="judges-remarks">Judges’ remarks:</h2>
<p>Do you understand how this program works? You may have to go over and
over the output again.</p>
<p>Do you understand how this program works? You may have to go over and over the
output again.</p>
<h2 id="authors-remarks">Author’s remarks:</h2>
<h3 id="summary">Summary:</h3>
<p>Scramble/unscramble to single file:</p>
@@ -181,85 +180,74 @@ over the output again.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> input.txt <span class="kw">|</span> <span class="ex">ruby</span> prog.c</span></code></pre></div>
<p>Input must be in UTF-8 encoding.</p>
<h3 id="details">Details:</h3>
<p>This is a text scrambling utility. To scramble text, specify input
file name as the first argument:</p>
<p>This is a text scrambling utility. To scramble text, specify input file name as
the first argument:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> input.txt <span class="op">&gt;</span> output.txt</span></code></pre></div>
<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>
<div class="sourceCode" id="cb10"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="fu">cat</span> output.txt</span></code></pre></div>
<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 in such a way that
characters are printed in random order. This effect is more visible if
there is a delay after each character is printed. For convenience, a
utility is included in the source to output characters slowly:</p>
<div class="sourceCode" id="cb11"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> input.txt <span class="kw">|</span> <span class="ex">ruby</span> prog.c</span></code></pre></div>
<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>
<div class="sourceCode" id="cb12"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> input.txt <span class="kw">|</span> <span class="ex">./prog</span> <span class="at">-</span> <span class="kw">|</span> <span class="ex">./prog</span> <span class="at">-</span> <span class="kw">|</span> <span class="ex">...</span></span></code></pre></div>
<div class="sourceCode" id="cb10"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="fu">cat</span> output.txt</span></code></pre></div>
<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 in such a way that characters are printed in random
order. This effect is more visible if there is a delay after each character is
printed. For convenience, a utility is included in the source to output
characters slowly:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> input.txt <span class="kw">|</span> <span class="ex">ruby</span> prog.c</span></code></pre></div>
<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>
<div class="sourceCode" id="cb12"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> input.txt <span class="kw">|</span> <span class="ex">./prog</span> <span class="at">-</span> <span class="kw">|</span> <span class="ex">./prog</span> <span class="at">-</span> <span class="kw">|</span> <span class="ex">...</span></span></code></pre></div>
<p>You can also split the input to multiple files, each getting a subset
of the original input characters:</p>
<div class="sourceCode" id="cb13"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> input.txt output1.txt output2.txt ...</span>
<div class="sourceCode" id="cb13"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> input.txt output1.txt output2.txt ...</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="fu">cat</span> output1.txt output2.txt ... <span class="op">&gt;</span> unscrambled.txt</span></code></pre></div>
<p>You can only unscramble files with <code>cat</code> if the input fits
in a single terminal screen. If you don’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 <code>stdin</code> and unscrambled to
<code>stdout</code>:</p>
<div class="sourceCode" id="cb14"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> <span class="op">&lt;</span> scrambled.txt <span class="op">&gt;</span> unscrambled.txt</span></code></pre></div>
<p>You can only unscramble files with <code>cat</code> if the input fits in a single
terminal screen. If you don’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 <code>stdin</code> and unscrambled to <code>stdout</code>:</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> <span class="op">&lt;</span> scrambled.txt <span class="op">&gt;</span> unscrambled.txt</span></code></pre></div>
<p>Where this is useful is that if you scramble the input to multiple
files and unscramble each output file individually, those output files
can be printed on transparencies and distributed separately.</p>
<div class="sourceCode" id="cb15"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> input.txt output1.txt output2.txt output3.txt</span>
files and unscramble each output file individually, those output
files can be printed on transparencies and distributed separately.</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> input.txt output1.txt output2.txt output3.txt</span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> <span class="op">&lt;</span> output1.txt <span class="op">&gt;</span> layer1.txt</span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> <span class="op">&lt;</span> output2.txt <span class="op">&gt;</span> layer2.txt</span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> <span class="op">&lt;</span> output3.txt <span class="op">&gt;</span> layer3.txt</span></code></pre></div>
<p>In other words, this is a utility for facilitating <a
href="https://en.wikipedia.org/wiki/Visual_cryptography">visual
cryptography</a>.</p>
<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>
<div class="sourceCode" id="cb16"><pre
class="sourceCode sh"><code class="sourceCode bash"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> input.txt <span class="kw">|</span> <span class="ex">./prog</span></span></code></pre></div>
<div class="sourceCode" id="cb16"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./prog</span> input.txt <span class="kw">|</span> <span class="ex">./prog</span></span></code></pre></div>
<h3 id="features">Features:</h3>
<h4 id="utf-8-support">UTF-8 support:</h4>
<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 the cursor is positioned correctly for most CJK input. <a
href="sample_input.txt">sample_input.txt</a> demonstrates this feature
with a mix of Basic Latin and Japanese characters.</p>
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 the cursor is positioned correctly for most CJK
input. <a href="sample_input.txt">sample_input.txt</a> 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>
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>
<h3 id="error-handling">Error handling</h3>
<p>If any file can not be opened for reading or writing, an error is
printed to <code>stderr</code>, and the utility will exit with nonzero
status.</p>
printed to <code>stderr</code>, and the utility will exit with nonzero status.</p>
<p>If there isn’t enough memory, the utility will likely crash.</p>
<p>If input contains CR-LF end of line sequences, those <code>CR</code>s
are silently dropped. In fact, most control codes are silently ignored
except line feeds (preserved) and tabs (expanded to 8 spaces).</p>
<p>If input contains CR-LF end of line sequences, those <code>CR</code>s are silently
dropped. In fact, most control codes are silently ignored except line
feeds (preserved) and tabs (expanded to 8 spaces).</p>
<h3 id="compatibility">Compatibility</h3>
<p>Verified to work and compiles without warnings on these
environments:</p>
<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>
@@ -268,72 +256,45 @@ environments:</p>
<li>gcc 4.8.4 on Linux</li>
</ul>
<h3 id="full-version">Full version</h3>
<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. <a href="violet.c">violet.c</a> 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 <a
href="https://en.wikipedia.org/wiki/Violet_Evergarden">Violet
Evergarden</a> in the story with the same name, the character who is
highly skilled in writing letters.</p>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0
License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights
Reserved. You are free to share and adapt this file under the terms of
this license:</p>
<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.
<a href="violet.c">violet.c</a> 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 <a href="https://en.wikipedia.org/wiki/Violet_Evergarden">Violet
Evergarden</a> in the story with
the same name, the character who is highly skilled in writing letters.</p>
<h2 id="copyright-and-cc-by-sa-4.0-license">Copyright and CC BY-SA 4.0 License:</h2>
<p>This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved.
You are free to share and adapt this file under the terms of this license:</p>
<pre><code>Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)</code></pre>
<p>For more information, see:
https://creativecommons.org/licenses/by-sa/4.0/</p>
<p>For more information, see: https://creativecommons.org/licenses/by-sa/4.0/</p>
<!-- END: this line ends content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
<!-- START: this line starts content for HTML phase 22 by: bin/output-index-inventory.sh via bin/md2html.sh -->
<!-- START: this line starts content generated by: bin/output-index-inventory.sh -->
<h1 id="inventory-for-2019yang"><a name="inventory"></a>Inventory for
2019/yang</h1>
<h1 id="inventory-for-2019yang"><a name="inventory"></a>Inventory for 2019/yang</h1>
<p><a href="#top">Jump to top</a></p>
<h2 id="primary-files">Primary files</h2>
<ul>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/yang/prog.c">prog.c</a>
- entry source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/yang/Makefile">Makefile</a>
- entry Makefile</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/yang/prog.orig.c">prog.orig.c</a>
- original source</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/yang/ioccc.txt">ioccc.txt</a>
- sample input</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/yang/sample_input.txt">sample_input.txt</a>
- sample input</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/yang/try.sh">try.sh</a>
- how to run</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/yang/violet.c">violet.c</a>
- source formatter as ASCII Violet Evergarden</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/yang/prog.c">prog.c</a> - entry source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/yang/Makefile">Makefile</a> - entry Makefile</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/yang/prog.orig.c">prog.orig.c</a> - original source</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/yang/ioccc.txt">ioccc.txt</a> - sample input</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/yang/sample_input.txt">sample_input.txt</a> - sample input</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/yang/try.sh">try.sh</a> - how to run</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/yang/violet.c">violet.c</a> - source formatter as ASCII Violet Evergarden</li>
<li><a href="spoiler.html">spoiler.html</a> - SPOILER WARNING</li>
<li><a href="2019_yang.tar.bz2">2019_yang.tar.bz2</a> - download entry
source</li>
<li><a href="2019_yang.tar.bz2">2019_yang.tar.bz2</a> - download entry source</li>
</ul>
<h2 id="secondary-files">Secondary files</h2>
<ul>
<li><a href="index.html">index.html</a> - entry home page</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/yang/.entry.json">.entry.json</a>
- description of entry in JSON</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/yang/.gitignore">.gitignore</a>
- list of files that should not be committed under git</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/yang/.entry.json">.entry.json</a> - description of entry in JSON</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/yang/.gitignore">.gitignore</a> - list of files that should not be committed under git</li>
<li><a href=".path">.path</a> - directory path from top directory</li>
<li><a
href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/yang/README.md">README.md</a>
- markdown source for index.html</li>
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2019/yang/README.md">README.md</a> - markdown source for index.html</li>
</ul>
<!-- END: next line ends content generated by: bin/output-index-inventory.sh -->