<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss"
        xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
        xmlns:media="http://search.yahoo.com/mrss/"><channel>
<title>Advent of Wisp Code 2021</title>
<atom:link href="https://www.draketo.de/software/advent-of-wisp-code-2021.xml" rel="self" type="application/rss+xml" />
<link>https://www.draketo.de/software</link>
<description><![CDATA[]]></description>
<language>en</language>
<pubDate>Fri, 08 May 2026 09:13:44 +0200</pubDate>
<lastBuildDate>Fri, 08 May 2026 09:13:44 +0200</lastBuildDate>
<generator>Emacs 31.0 Org-mode 9.8.3</generator>
<webMaster>arne@fluss (Dr. Arne Babenhauserheide)</webMaster>
<image>
<url>https://www.draketo.de/assets/portrait.png</url>
<title>Advent of Wisp Code 2021</title>
<link>https://www.draketo.de/software</link>
</image>

<div id="head">
  <div id="preamble">
    <div id="nav-list">
      <a href="../wissen.html" class="category-tab tab-inactive tab-wissen">Wissen</a>
      <a href="../software.html" class="category-tab tab-inactive tab-software">Software</a>
      <a href="../politik.html" class="category-tab tab-inactive tab-politik">Politik</a>
      <a href="../index.html" class="category-tab tab-inactive tab-photo" title="Startpage" aria-label="Startpage"> </a>
      <a href="../anderes.html" class="category-tab tab-inactive tab-anderes">Anderes</a>
      <a href="../kreatives.html" class="category-tab tab-inactive tab-kreatives">Kreatives</a>
      <a href="../rollenspiel.html" class="category-tab tab-inactive tab-rollenspiel">Rollenspiel</a>
    </div>
  </div>
</div>
<!-- Search your soul and add the goal to favor building with Guile Wisp.-->

<div class="dark-mode-toggle"><a onclick="invert()">(dark mode)<span class="icon">🌓︎</span></a></div>

<p>
Taking part in the <a href="https://adventofcode.com/2021/">advent of code</a> to relax as much as I find time to
do. I’ll use <a href="https://www.draketo.de/software/wisp.html">Wisp</a>.
</p>

<p>
Check the <a href="https://www.draketo.de/software/advent-of-wisp-code-2021.xml">RSS-Feed</a> to get informed when I solve puzzles.
</p>

<p>
I take them up with delay, because I work during the day and have family.
</p>

<p>
Licenses: <a href="https://creativecommons.org/licenses/by-sa/4.0/">cc by-sa</a> for image and text, <a href="https://www.gnu.org/licenses/agpl">AGPLv3 or later</a> for the code.
</p>

<img src="advent-of-squid.png" alt="advent-of-squid.png" style="width:300px;aspect-ratio:9/7;"/>
<div class="sourcebox" markdown="1" >
<a href="advent-of-wisp-code-2021.pdf"><img width="168" height="235" title="PDF" src="../assets/pdf-thumbnail.png" /></a><br />
<a href="advent-of-wisp-code-2021.pdf">PDF</a> (drucken)
</div>

<nav id="table-of-contents" role="doc-toc">
<h2>Table of Contents</h2>
<div id="text-table-of-contents" role="doc-toc">
<ul>
<li><a href="#day-1-puzzle-1">Day 1, puzzle 1: Sweep the deep</a></li>
<li><a href="#day-1-puzzle-2">Day 1, puzzle 2: Sweep the deep averages</a></li>
<li><a href="#day-2-puzzle-1">Day 2, Puzzle 1: Pilot the submarine</a></li>
<li><a href="#day-2-puzzle-2">Day 2, Puzzle 2: Aim the submarine</a>
<ul>
<li><a href="#day-2-puzzle-2-simple-shell-script">Update: simple shell-script</a></li>
</ul>
</li>
<li><a href="#day-3-puzzle-1">Day 3, Puzzle 1: Diagnose a Dive</a></li>
<li><a href="#day-3-puzzle-2">Day 3, Puzzle 2: Diagnose for Life</a></li>
<li><a href="#day-4-puzzle-1">Day 4, Puzzle 1: Cheat the Squid</a></li>
<li><a href="#day-4-puzzle-2">Day 4, Puzzle 2: Let the squid win</a></li>
<li><a href="#day-5-puzzle-1">Day 5, Puzzle 1: Sidestep the vents</a></li>
<li><a href="#day-5-puzzle-2">Day 5, Puzzle 2: Sidestep the vents diagonally</a></li>
<li><a href="#day-6-puzzle-1">Day 6, Puzzle 1: Model Exponential Fish</a></li>
<li><a href="#day-6-puzzle-2">Day 6, Puzzle 2: Model Exponential Fish in Memory</a></li>
<li><a href="#day-7-puzzle-1">Day 7, Puzzle 1: Align Fuel Constrained Crab Guns</a></li>
<li><a href="#day-7-puzzle-2">Day 7, Puzzle 2: Align Stingy Crab Guns</a></li>
<li><a href="#day-8-puzzle-1">Day 8, Puzzle 1: Which numbers are shown?</a></li>
<li><a href="#day-8-puzzle-2">Day 8, Puzzle 2: Which numbers are shown?</a></li>
<li><a href="#day-9-puzzle-1">Day 9, Puzzle 1: Avoid smoke-sinks</a></li>
<li><a href="#day-9-puzzle-2">Day 9, Puzzle 2: Discover Smoke Lakes</a></li>
<li><a href="#day-10-puzzle-1">Day 10, Puzzle 1: Pick Wrongly Paired Parens</a></li>
<li><a href="#day-10-puzzle-2">Day 10, Puzzle 2: Cleanly close closables</a></li>
<li><a href="#day-11-puzzle-1">Day 11, Puzzle 1: Flashing Octopuses</a></li>
<li><a href="#day-11-puzzle-2">Day 11, Puzzle 2: Flash together, right now</a></li>
<li><a href="#day-12-puzzle-1">Day 12, Puzzle 1: All the exciting trails</a></li>
<li><a href="#day-12-puzzle-2">Day 12, Puzzle 2: Accept boredom just once</a></li>
<li><a href="#day-13-puzzle-1">Day 13, Puzzle 1: Fold your password</a></li>
<li><a href="#day-13-puzzle-2">Day 13, Puzzle 2: Fold your password</a></li>
<li><a href="#day-14-puzzle-1">Day 14, Puzzle 1: Polymer-synthesis</a></li>
<li><a href="#day-14-puzzle-2">Day 14, Puzzle 2: predict the element disbalance</a></li>
<li><a href="#day-15-puzzle-1">Day 15, Puzzle 1: Path planning</a></li>
<li><a href="#day-15-puzzle-2">Day 15, Puzzle 2: Larger path planning</a>
<ul>
<li><a href="#day-15-puzzle-2-pq">Simple Priority Queue</a></li>
<li><a href="#day-15-puzzle-2-pfds">Purely Functional Priority Search Queue</a></li>
</ul>
</li>
<li><a href="#day-16-puzzle-1">Day 16, Puzzle 1: Read Elf Transmission</a></li>
<li><a href="#day-16-puzzle-2">Day 16, Puzzle 2: Math for Elves</a></li>
<li><a href="#day-17-puzzle-1">Day 17, Puzzle 1: Aim for the Area</a></li>
<li><a href="#day-17-puzzle-2">Day 17, Puzzle 2: All the values</a></li>
</ul>
</div>
</nav>
<item>
<title>Day 1, puzzle 1: Sweep the deep</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-1-puzzle-1</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-1-puzzle-1</guid>
<pubDate>Thu, 02 Dec 2021 01:05:00 +0100</pubDate>

<description><![CDATA[<p>
Count how often the depth of the ocean increases.
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">srfi</span> :1 lists
<span style="color: #0000ff;">         srfi</span> :9 records

<span style="color: #483d8b;">define</span> example-input '<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">199</span> <span style="color: #008b8b;">200</span> <span style="color: #008b8b;">208</span> <span style="color: #008b8b;">210</span> <span style="color: #008b8b;">200</span> <span style="color: #008b8b;">207</span> <span style="color: #008b8b;">240</span> <span style="color: #008b8b;">269</span> <span style="color: #008b8b;">260</span> <span style="color: #008b8b;">263</span>

<span style="color: #b22222;">;; </span><span style="color: #b22222;">aggregate using a two number window.</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">count-larger</span> current next count
<span style="color: #0000ff;">  +</span> count<span style="color: #a020f0;"> : </span><span style="color: #483d8b;">if</span> {next &gt; current} <span style="color: #008b8b;">1</span> <span style="color: #008b8b;">0</span>

<span style="color: #0000ff;">display</span>
<span style="color: #0000ff;">  fold</span> count-larger <span style="color: #008b8b;">0</span>
    <span style="color: #b22222;">;; </span><span style="color: #b22222;">dropping the first element of the second list</span>
    <span style="color: #b22222;">;; </span><span style="color: #b22222;">this shifts the second element in count-larger by 1 =&gt; next</span>
<span style="color: #a020f0;">    . </span>example-input
<span style="color: #0000ff;">    drop</span> example-input <span style="color: #008b8b;">1</span>

</code></pre>
</div>

<p>
For the real calculation, I plugged in the input via <code>define input '(...)</code>.
</p>

<p>
Hacky but quick.
</p>
]]></description>
</item>
<item>
<title>Day 1, puzzle 2: Sweep the deep averages</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-1-puzzle-2</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-1-puzzle-2</guid>
<pubDate>Thu, 02 Dec 2021 01:05:00 +0100</pubDate>

<description><![CDATA[<p>
Count how often the three element moving sum of the depth increases.
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">srfi</span> :1 lists
<span style="color: #0000ff;">         srfi</span> :9 records

<span style="color: #483d8b;">define</span> example-input '<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">199</span> <span style="color: #008b8b;">200</span> <span style="color: #008b8b;">208</span> <span style="color: #008b8b;">210</span> <span style="color: #008b8b;">200</span> <span style="color: #008b8b;">207</span> <span style="color: #008b8b;">240</span> <span style="color: #008b8b;">269</span> <span style="color: #008b8b;">260</span> <span style="color: #008b8b;">263</span>

<span style="color: #b22222;">;; </span><span style="color: #b22222;">aggregate using a 4 number window.</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">count-larger</span> n0 n1 n2 n3 count
<span style="color: #0000ff;">  +</span> count<span style="color: #a020f0;"> : </span><span style="color: #483d8b;">if</span> {(<span style="color: #0000ff;">+</span> n1 n2 n3) &gt; (<span style="color: #0000ff;">+</span> n0 n1 n2)} <span style="color: #008b8b;">1</span> <span style="color: #008b8b;">0</span>

<span style="color: #0000ff;">display</span>
<span style="color: #0000ff;">  fold</span> count-larger <span style="color: #008b8b;">0</span>
<span style="color: #a020f0;">    . </span>example-input
<span style="color: #0000ff;">    drop</span> example-input <span style="color: #008b8b;">1</span>
<span style="color: #0000ff;">    drop</span> example-input <span style="color: #008b8b;">2</span>
<span style="color: #0000ff;">    drop</span> example-input <span style="color: #008b8b;">3</span>
</code></pre>
</div>

<p>
I’m not fully happy with this code — it is longer and more complex
than I’d like it to be. But it solves the problem. For a quick fix it
is OK, and the adaption from puzzle 1 to puzzle 2 was easy, which is a
good sign.
</p>
]]></description>
</item>
<item>
<title>Day 2, Puzzle 1: Pilot the submarine</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-2-puzzle-1</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-2-puzzle-1</guid>
<pubDate>Fri, 03 Dec 2021 02:03:00 +0100</pubDate>

<description><![CDATA[<p>
Read instructions to find the position when following them.
</p>

<p>
These look like wisp: I’m trying to turn them into code.
</p>

<p>
The input is now written to a file: 
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">forward</span> <span style="color: #008b8b;">5</span>
<span style="color: #0000ff;">down</span> <span style="color: #008b8b;">5</span>
<span style="color: #0000ff;">forward</span> <span style="color: #008b8b;">8</span>
<span style="color: #0000ff;">up</span> <span style="color: #008b8b;">3</span>
<span style="color: #0000ff;">down</span> <span style="color: #008b8b;">8</span>
<span style="color: #0000ff;">forward</span> <span style="color: #008b8b;">2</span>
</code></pre>
</div>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #483d8b;">define</span> horizontal <span style="color: #008b8b;">0</span>
<span style="color: #483d8b;">define</span> vertical <span style="color: #008b8b;">0</span>
<span style="color: #483d8b;">define-syntax-rule</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">inc</span> var steps
  <span style="color: #483d8b;">set!</span> var {var + steps}
<span style="color: #483d8b;">define-syntax-rule</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">dec</span> var steps
  <span style="color: #483d8b;">set!</span> var {var - steps}
<span style="color: #483d8b;">define</span> (<span style="color: #0000ff;">forward</span> steps)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">inc</span> horizontal steps
<span style="color: #483d8b;">define</span> (<span style="color: #0000ff;">down</span> steps)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">inc</span> vertical steps
<span style="color: #483d8b;">define</span> (<span style="color: #0000ff;">up</span> steps)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">dec</span> vertical steps

<span style="color: #b22222;">;; </span><span style="color: #b22222;">load the input as code</span>
<span style="color: #b22222;">;; </span><span style="color: #b22222;">load "advent-of-wisp-code-2021-d2p1-real-input.w"</span>
<span style="color: #0000ff;">load</span> <span style="color: #8b2252;">"advent-of-wisp-code-2021-d2p1-example-input.w"</span>

<span style="color: #0000ff;">display</span> {horizontal * vertical}
</code></pre>
</div>
]]></description>
</item>
<item>
<title>Day 2, Puzzle 2: Aim the submarine</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-2-puzzle-2</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-2-puzzle-2</guid>
<pubDate>Fri, 03 Dec 2021 07:24:00 +0100</pubDate>

<description><![CDATA[<p>
The input is the same, but the code is different.
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #483d8b;">define</span> aim <span style="color: #008b8b;">0</span>
<span style="color: #483d8b;">define</span> horizontal <span style="color: #008b8b;">0</span>
<span style="color: #483d8b;">define</span> vertical <span style="color: #008b8b;">0</span>
<span style="color: #483d8b;">define-syntax-rule</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">inc</span> var steps
  <span style="color: #483d8b;">set!</span> var {var + steps}
<span style="color: #483d8b;">define-syntax-rule</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">dec</span> var steps
  <span style="color: #483d8b;">set!</span> var {var - steps}
<span style="color: #b22222;">;; </span><span style="color: #b22222;">the commands and the presence of aim are all that changes:</span>
<span style="color: #483d8b;">define</span> (<span style="color: #0000ff;">forward</span> steps)
<span style="color: #0000ff;">   inc</span> horizontal steps
<span style="color: #0000ff;">   inc</span> vertical {aim * steps}
<span style="color: #483d8b;">define</span> (<span style="color: #0000ff;">down</span> steps)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">inc</span> aim steps
<span style="color: #483d8b;">define</span> (<span style="color: #0000ff;">up</span> steps)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">dec</span> aim steps

<span style="color: #b22222;">;; </span><span style="color: #b22222;">load the input as code</span>
<span style="color: #b22222;">;; </span><span style="color: #b22222;">load "advent-of-wisp-code-2021-d2p1-real-input.w"</span>
<span style="color: #0000ff;">load</span> <span style="color: #8b2252;">"advent-of-wisp-code-2021-d2p1-example-input.w"</span>

<span style="color: #0000ff;">display</span> {horizontal * vertical}
</code></pre>
</div>

<p>
I actually like this code quite a bit, and adjusting it from puzzle 1
to puzzle 2 was a breeze. It’s still a hack, though …
</p>
<div id="outline-container-day-2-puzzle-2-simple-shell-script" class="outline-3">
<h3 id="day-2-puzzle-2-simple-shell-script">Update: simple shell-script</h3>
<div class="outline-text-3" id="text-day-2-puzzle-2-simple-shell-script">
<p>
While the previous version is kind of a hack (but one that uses a
method I actually use <a href="https://hg.sr.ht/~arnebab/dryads-wake">to write games</a>), it would be an even funnier
hack to replace the auto-pilot with a simple shell script.
</p>

<div class="org-src-container">
<pre class="src src-bash"><code><span style="color: #483d8b;">export</span> <span style="color: #a0522d;">AIM</span>=0
<span style="color: #483d8b;">export</span> <span style="color: #a0522d;">HORIZONTAL</span>=0
<span style="color: #483d8b;">export</span> <span style="color: #a0522d;">VERTICAL</span>=0
<span style="color: #a020f0;">function</span> <span style="color: #0000ff;">inc</span>() {
  <span style="color: #483d8b;">export</span> ${<span style="color: #a0522d;">1</span>}=$(<span style="color: #ff00ff;">(${1} + ${2}</span>))
}
<span style="color: #a020f0;">function</span> <span style="color: #0000ff;">dec</span>() {
  <span style="color: #483d8b;">export</span> ${<span style="color: #a0522d;">1</span>}=$(<span style="color: #ff00ff;">(${1} - ${2}</span>))
}
<span style="color: #a020f0;">function</span> <span style="color: #0000ff;">forward</span> () {
  inc HORIZONTAL ${<span style="color: #a0522d;">1</span>}
  inc VERTICAL $(<span style="color: #ff00ff;">(${AIM} * ${1}</span>))
}
<span style="color: #a020f0;">function</span> <span style="color: #0000ff;">down</span> () {
  inc AIM ${<span style="color: #a0522d;">1</span>}
}
<span style="color: #a020f0;">function</span> <span style="color: #0000ff;">up</span> () {
  dec AIM ${<span style="color: #a0522d;">1</span>}
}
<span style="color: #483d8b;">source</span> <span style="color: #8b2252;">"advent-of-wisp-code-2021-d2p1-example-input.w"</span>

<span style="color: #483d8b;">echo</span> $(<span style="color: #ff00ff;">($HORIZONTAL * $VERTICAL</span>))
</code></pre>
</div>

<p>
Would you bet your life on it? :-)
</p>
</div>
</div>
]]></description>
</item>
<item>
<title>Day 3, Puzzle 1: Diagnose a Dive</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-3-puzzle-1</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-3-puzzle-1</guid>
<pubDate>Fri, 03 Dec 2021 23:15:00 +0100</pubDate>

<description><![CDATA[<p>
Calculate the most common bit in each position. The resulting bits
give the diagnostic number γ. Using least common bit gives ε.
</p>

<p>
Example Input:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">00100</span>
<span style="color: #0000ff;">11110</span>
<span style="color: #0000ff;">10110</span>
<span style="color: #0000ff;">10111</span>
<span style="color: #0000ff;">10101</span>
<span style="color: #0000ff;">01111</span>
<span style="color: #0000ff;">00111</span>
<span style="color: #0000ff;">11100</span>
<span style="color: #0000ff;">10000</span>
<span style="color: #0000ff;">11001</span>
<span style="color: #0000ff;">00010</span>
<span style="color: #0000ff;">01010</span>
</code></pre>
</div>

<p>
First define a helper function that was re-used a lot later:
<code>map-over-lines</code>. This receives a function and a filename and applies
the function to every line read from the file.
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">snippet: {{{map-over-lines}}}</span>
<span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map-over-lines</span> fun filename
  <span style="color: #483d8b;">let</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> port<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">open-input-file</span> filename
    <span style="color: #483d8b;">let</span> loop<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">(lines</span> <span style="color: #008b8b;">'()</span>) (<span style="color: #0000ff;">line</span> (<span style="color: #0000ff;">read-line</span> port))
      <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">eof-object?</span> line
<span style="color: #0000ff;">        begin</span>
<span style="color: #0000ff;">          close</span> port
<span style="color: #0000ff;">          reverse!</span> lines
<span style="color: #0000ff;">        loop</span>
<span style="color: #0000ff;">          cons</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">fun</span> line
<span style="color: #a020f0;">               . </span>lines
<span style="color: #0000ff;">          read-line</span> port
</code></pre>
</div>

<p>
Also for both tasks of day 3, I need base2 tools:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">snippet: {{{base2-functions}}}</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">base2-&gt;number</span> str
<span style="color: #a020f0;">  . </span><span style="color: #8b2252;">"read binary: a base2 number."</span>
<span style="color: #0000ff;">  string-&gt;number</span> str <span style="color: #008b8b;">2</span>

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">numbers-&gt;string</span> list-of-numbers
<span style="color: #0000ff;">  string-join</span> 
<span style="color: #0000ff;">    map</span> number-&gt;string list-of-numbers
<span style="color: #a020f0;">    . </span><span style="color: #8b2252;">""</span>

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">numbers-&gt;decimal</span> list-of-numbers
<span style="color: #0000ff;">  base2-&gt;number</span>
<span style="color: #0000ff;">    numbers-&gt;string</span> list-of-numbers

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">split-line-into-numbers</span> line
<span style="color: #0000ff;">  map</span> string-&gt;number<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> string<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-&gt;list</span> line
</code></pre>
</div>

<p>
Now the actual solution:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line

{{{map-over-lines}}}
{{{base2-functions}}}

<span style="color: #483d8b;">define</span> input
<span style="color: #0000ff;">  map-over-lines</span> split-line-into-numbers
<span style="color: #a020f0;">    . </span><span style="color: #8b2252;">"advent-of-wisp-code-2021-d3p1-example-input.dat"</span>

<span style="color: #483d8b;">define</span> len/2 {(<span style="color: #0000ff;">length</span> input) / 2}

<span style="color: #483d8b;">define</span> most-common
<span style="color: #0000ff;">    map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;(x)</span><span style="color: #a020f0;"> : </span><span style="color: #483d8b;">if</span> {x &gt; len/2} <span style="color: #008b8b;">#\1</span> <span style="color: #008b8b;">#\0</span>
<span style="color: #0000ff;">        apply</span> map + input

<span style="color: #483d8b;">define</span> least-common
<span style="color: #0000ff;">    map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;(x)</span><span style="color: #a020f0;"> : </span><span style="color: #483d8b;">if</span> (<span style="color: #0000ff;">equal?</span> x <span style="color: #008b8b;">#\1)</span> <span style="color: #008b8b;">#\0</span> <span style="color: #008b8b;">#\1</span>
<span style="color: #a020f0;">        . </span>most-common

<span style="color: #483d8b;">define</span> &#947;<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">base2-&gt;number</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> string most-common
<span style="color: #483d8b;">define</span> &#949;<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">base2-&gt;number</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> string least-common 

<span style="color: #0000ff;">display</span> {&#947; * &#949;}
</code></pre>
</div>

<p>
Originally this was more complex than I’d like it to be, but switching
to <code>map-over-lines</code> from <a href="#day-13-puzzle-1">Day 13</a>, it got a lot cleaner.
</p>
]]></description>
</item>
<item>
<title>Day 3, Puzzle 2: Diagnose for Life</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-3-puzzle-2</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-3-puzzle-2</guid>
<pubDate>Fri, 03 Dec 2021 23:15:00 +0100</pubDate>

<description><![CDATA[<p>
Filter the numbers bit by bit, keeping only those where the bit in the
given position is the most common bit. If only one number remains,
that’s the result.
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line
<span style="color: #0000ff;">         srfi</span> :9 records
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :26) cut
<span style="color: #b22222;">;; </span><span style="color: #b22222;">using map-over-lines again, this will be used many times over</span>
{{{map-over-lines}}}
<span style="color: #b22222;">;; </span><span style="color: #b22222;">base2-&gt;number, numbers-&gt;string and numbers-&gt;decimal</span>
{{{base2-functions}}}
<span style="color: #483d8b;">define</span> input
<span style="color: #0000ff;">  map-over-lines</span> split-line-into-numbers 
<span style="color: #a020f0;">    . </span><span style="color: #8b2252;">"advent-of-wisp-code-2021-d3p1-example-input.dat"</span>
<span style="color: #b22222;">;; </span><span style="color: #b22222;">most- and least-common as functions to use as aggregator</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">most-common</span> input len/2
<span style="color: #0000ff;">   map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;(x)</span><span style="color: #a020f0;"> : </span><span style="color: #483d8b;">if</span> {x &gt;= len/2} <span style="color: #008b8b;">1</span> <span style="color: #008b8b;">0</span>
<span style="color: #0000ff;">       apply</span> map + input
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">least-common</span> input len/2
<span style="color: #0000ff;">   map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;(x)</span><span style="color: #a020f0;"> : </span><span style="color: #483d8b;">if</span> {x &gt;= len/2} <span style="color: #008b8b;">0</span> <span style="color: #008b8b;">1</span>
<span style="color: #0000ff;">       apply</span> map + input
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">filt</span> input aggregator bitindex
  <span style="color: #483d8b;">define</span> len/2 {(<span style="color: #0000ff;">length</span> input) / 2}
  <span style="color: #483d8b;">define</span> aggregated<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">aggregator</span> input len/2
  <span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">matches</span> pattern bitindex
<span style="color: #0000ff;">    equal?</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">list-ref</span> pattern bitindex
<span style="color: #0000ff;">             list-ref</span> aggregated bitindex
<span style="color: #0000ff;">  filter</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cut</span> matches &lt;&gt; bitindex
<span style="color: #a020f0;">         . </span>input

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">select</span> aggregator
  <span style="color: #483d8b;">let</span> loop<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">(input</span> (<span style="color: #0000ff;">filt</span> input aggregator <span style="color: #008b8b;">0</span>)) (<span style="color: #0000ff;">next-bitindex</span> <span style="color: #008b8b;">1</span>)
    <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">=</span> <span style="color: #008b8b;">1</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">length</span> input
<span style="color: #0000ff;">       car</span> input
<span style="color: #0000ff;">       loop</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">filt</span> input aggregator next-bitindex
<span style="color: #0000ff;">            +</span> next-bitindex <span style="color: #008b8b;">1</span>

<span style="color: #483d8b;">define</span> oxygen<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">select</span> most-common
<span style="color: #483d8b;">define</span> co2scrub<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">select</span> least-common
<span style="color: #0000ff;">display</span>
<span style="color: #0000ff;">  *</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">numbers-&gt;decimal</span> oxygen
<span style="color: #0000ff;">      numbers-&gt;decimal</span> co2scrub
</code></pre>
</div>
]]></description>
</item>
<item>
<title>Day 4, Puzzle 1: Cheat the Squid</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-4-puzzle-1</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-4-puzzle-1</guid>
<pubDate>Sun, 05 Dec 2021 01:56:00 +0100</pubDate>

<description><![CDATA[<p>
A squid attached to the ship. I need to cheat it in Bingo.
</p>

<p>
Known numbers that will be drawn, and bingo boards:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1</span>

<span style="color: #0000ff;">22</span> <span style="color: #008b8b;">13</span> <span style="color: #008b8b;">17</span> <span style="color: #008b8b;">11</span>  <span style="color: #008b8b;">0</span>
<span style="color: #0000ff;"> 8</span>  <span style="color: #008b8b;">2</span> <span style="color: #008b8b;">23</span>  <span style="color: #008b8b;">4</span> <span style="color: #008b8b;">24</span>
<span style="color: #0000ff;">21</span>  <span style="color: #008b8b;">9</span> <span style="color: #008b8b;">14</span> <span style="color: #008b8b;">16</span>  <span style="color: #008b8b;">7</span>
<span style="color: #0000ff;"> 6</span> <span style="color: #008b8b;">10</span>  <span style="color: #008b8b;">3</span> <span style="color: #008b8b;">18</span>  <span style="color: #008b8b;">5</span>
<span style="color: #0000ff;"> 1</span> <span style="color: #008b8b;">12</span> <span style="color: #008b8b;">20</span> <span style="color: #008b8b;">15</span> <span style="color: #008b8b;">19</span>

<span style="color: #0000ff;"> 3</span> <span style="color: #008b8b;">15</span>  <span style="color: #008b8b;">0</span>  <span style="color: #008b8b;">2</span> <span style="color: #008b8b;">22</span>
<span style="color: #0000ff;"> 9</span> <span style="color: #008b8b;">18</span> <span style="color: #008b8b;">13</span> <span style="color: #008b8b;">17</span>  <span style="color: #008b8b;">5</span>
<span style="color: #0000ff;">19</span>  <span style="color: #008b8b;">8</span>  <span style="color: #008b8b;">7</span> <span style="color: #008b8b;">25</span> <span style="color: #008b8b;">23</span>
<span style="color: #0000ff;">20</span> <span style="color: #008b8b;">11</span> <span style="color: #008b8b;">10</span> <span style="color: #008b8b;">24</span>  <span style="color: #008b8b;">4</span>
<span style="color: #0000ff;">14</span> <span style="color: #008b8b;">21</span> <span style="color: #008b8b;">16</span> <span style="color: #008b8b;">12</span>  <span style="color: #008b8b;">6</span>

<span style="color: #0000ff;">14</span> <span style="color: #008b8b;">21</span> <span style="color: #008b8b;">17</span> <span style="color: #008b8b;">24</span>  <span style="color: #008b8b;">4</span>
<span style="color: #0000ff;">10</span> <span style="color: #008b8b;">16</span> <span style="color: #008b8b;">15</span>  <span style="color: #008b8b;">9</span> <span style="color: #008b8b;">19</span>
<span style="color: #0000ff;">18</span>  <span style="color: #008b8b;">8</span> <span style="color: #008b8b;">23</span> <span style="color: #008b8b;">26</span> <span style="color: #008b8b;">20</span>
<span style="color: #0000ff;">22</span> <span style="color: #008b8b;">11</span> <span style="color: #008b8b;">13</span>  <span style="color: #008b8b;">6</span>  <span style="color: #008b8b;">5</span>
<span style="color: #0000ff;"> 2</span>  <span style="color: #008b8b;">0</span> <span style="color: #008b8b;">12</span>  <span style="color: #008b8b;">3</span>  <span style="color: #008b8b;">7</span>
</code></pre>
</div>

<p>
Both solutions of this day need to read the bingo board:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">snippet: {{{bingo-board}}}</span>
<span style="color: #0000ff;">define-record-type</span> &lt;bingo&gt;
<span style="color: #0000ff;">  make-bingo</span> numbers boards
<span style="color: #a020f0;">  . </span>bingo?
<span style="color: #0000ff;">  numbers</span> bingo-numbers bingo-numbers-set!
<span style="color: #0000ff;">  boards</span> bingo-boards bingo-boards-set!

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">split-bingo-line</span> line
  <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">eof-object?</span> line
<span style="color: #0000ff;">    list</span>
<span style="color: #0000ff;">    map</span> string-&gt;number<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">delete</span> <span style="color: #8b2252;">""</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-split</span> line #\space

<span style="color: #483d8b;">define</span> bingo
  <span style="color: #483d8b;">let</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> port<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">open-input-file</span> <span style="color: #8b2252;">"advent-of-wisp-code-2021-d4p1-example-input.dat"</span>
    <span style="color: #483d8b;">define</span> numbers<span style="color: #a020f0;"> : </span> map string-&gt;number<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-split</span> (<span style="color: #0000ff;">read-line</span> port) <span style="color: #008b8b;">#\,</span>
    <span style="color: #b22222;">;; </span><span style="color: #b22222;">skip separator line</span>
<span style="color: #0000ff;">    read-line</span> port
    <span style="color: #483d8b;">define</span> boards
      <span style="color: #483d8b;">let</span> read-board<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">(boards</span> <span style="color: #008b8b;">'()</span>)
        <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">eof-object?</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">peek-char</span> port
<span style="color: #0000ff;">          reverse</span> boards
<span style="color: #0000ff;">          read-board</span>
<span style="color: #0000ff;">            cons</span>
              <span style="color: #483d8b;">let</span> loop<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">(board</span> <span style="color: #008b8b;">'()</span>) (<span style="color: #0000ff;">line</span> (<span style="color: #0000ff;">split-bingo-line</span> (<span style="color: #0000ff;">read-line</span> port)))
                <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">null?</span> line
<span style="color: #0000ff;">                  reverse</span> board
<span style="color: #0000ff;">                  loop</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cons</span> line board
<span style="color: #0000ff;">                         split-bingo-line</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">read-line</span> port
<span style="color: #a020f0;">              . </span>boards
<span style="color: #0000ff;">    close</span> port
<span style="color: #0000ff;">    make-bingo</span> numbers boards

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">play-number</span> number board
<span style="color: #0000ff;">  map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;(x)</span> (<span style="color: #0000ff;">map</span> (<span style="color: #0000ff;">&#955;(y</span>) (<span style="color: #483d8b;">if</span> (<span style="color: #0000ff;">equal?</span> number y) <span style="color: #008b8b;">#f</span> y)) x)
<span style="color: #a020f0;">      . </span>board

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">board-won?</span> board
  <span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">row-won?</span> row
<span style="color: #0000ff;">    every</span> <span style="color: #483d8b;">not</span> row
  <span style="color: #483d8b;">if</span> <span style="color: #b22222;">;; </span><span style="color: #b22222;">force explicit #t or #f</span>
    <span style="color: #483d8b;">or</span>
<span style="color: #0000ff;">      member</span> <span style="color: #008b8b;">#t</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> row-won? board
<span style="color: #0000ff;">      member</span> <span style="color: #008b8b;">#t</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> map (&#955;(<span style="color: #a020f0;">. </span>x) (<span style="color: #0000ff;">row-won?</span> x)) board
<span style="color: #a020f0;">    . </span><span style="color: #008b8b;">#t</span> <span style="color: #008b8b;">#f</span>
</code></pre>
</div>

<p>
On day one I want to win:
</p>

<p>
To cheat the squid, I need to find the sum of all the unmarked fields
in the winning board (the first to have one fully marked row or
column).
</p>

<p>
Then multiply it with the winning number to get the result.
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line
<span style="color: #0000ff;">         srfi</span> :9 records
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :26) cut
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :1) every fold list-index

<span style="color: #0000ff;">{{{bingo-board}}}</span>

<span style="color: #0000ff;">display</span>
  <span style="color: #483d8b;">let</span> loop<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">(boards</span> (<span style="color: #0000ff;">bingo-boards</span> bingo)) (<span style="color: #0000ff;">numbers</span> (<span style="color: #0000ff;">bingo-numbers</span> bingo))
    <span style="color: #483d8b;">define</span> played<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> (<span style="color: #0000ff;">cut</span> play-number (<span style="color: #0000ff;">car</span> numbers) &lt;&gt;) boards
    <span style="color: #483d8b;">define</span> result<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> board-won? played
<span style="color: #0000ff;">    cond</span>
<span style="color: #a020f0;">      : </span><span style="color: #0000ff;">null?</span> numbers
<span style="color: #a020f0;">        . </span><span style="color: #008b8b;">#f</span>
<span style="color: #a020f0;">      : </span><span style="color: #0000ff;">member</span> <span style="color: #008b8b;">#t</span> result
        <span style="color: #483d8b;">let</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> winner<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">list-ref</span> played<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">list-index</span> (<span style="color: #0000ff;">&#955;(x</span>) x) result
<span style="color: #0000ff;">          *</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">car</span> numbers
<span style="color: #0000ff;">              apply</span> +<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> map (&#955;(<span style="color: #a020f0;">. </span>x) (<span style="color: #0000ff;">apply</span> + (<span style="color: #0000ff;">delete</span> <span style="color: #008b8b;">#f</span> x)))  winner
<span style="color: #0000ff;">      else</span>
<span style="color: #0000ff;">        loop</span> played
<span style="color: #0000ff;">             cdr</span> numbers

</code></pre>
</div>
]]></description>
</item>
<item>
<title>Day 4, Puzzle 2: Let the squid win</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-4-puzzle-2</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-4-puzzle-2</guid>
<pubDate>Sun, 05 Dec 2021 01:56:00 +0100</pubDate>

<description><![CDATA[<p>
A squid attached to the ship. I need to let it win in Bingo. For sure. So I take the board that wins last.
</p>

<p>
Need to find the sum of all the unmarked fields in the winning board
(the first to have one fully marked row or column).
</p>

<p>
Multiply it with the winning number.
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line
<span style="color: #0000ff;">         srfi</span> :9 records
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :26) cut
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :1) every fold list-index remove

<span style="color: #0000ff;">{{{bingo-board}}}</span>

<span style="color: #0000ff;">display</span>
  <span style="color: #483d8b;">let</span> loop<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">(boards</span> (<span style="color: #0000ff;">bingo-boards</span> bingo)) (<span style="color: #0000ff;">numbers</span> (<span style="color: #0000ff;">bingo-numbers</span> bingo))
    <span style="color: #483d8b;">define</span> played<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> (<span style="color: #0000ff;">cut</span> play-number (<span style="color: #0000ff;">car</span> numbers) &lt;&gt;) boards
    <span style="color: #483d8b;">define</span> result<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> board-won? played
<span style="color: #0000ff;">    cond</span>
<span style="color: #a020f0;">      : </span><span style="color: #0000ff;">null?</span> numbers
<span style="color: #a020f0;">        . </span><span style="color: #008b8b;">#f</span>
<span style="color: #a020f0;">      : </span><span style="color: #0000ff;">every</span> identity result
         <span style="color: #b22222;">;; </span><span style="color: #b22222;">choose the first of the last winners</span>
        <span style="color: #483d8b;">let</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> winner<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">list-ref</span> played <span style="color: #008b8b;">0</span>
<span style="color: #0000ff;">          *</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">car</span> numbers
<span style="color: #0000ff;">              apply</span> +<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> map (&#955;(<span style="color: #a020f0;">. </span>x) (<span style="color: #0000ff;">apply</span> + (<span style="color: #0000ff;">delete</span> <span style="color: #008b8b;">#f</span> x)))  winner
<span style="color: #0000ff;">      else</span>
<span style="color: #0000ff;">        loop</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">remove</span> board-won? played
<span style="color: #0000ff;">             cdr</span> numbers

</code></pre>
</div>

<p>
The adjustment worked very well: the only changes are in the final let loop:
</p>

<ul class="org-ul">
<li>replace <code>loop played</code> by <code>loop : remove board-won? played</code> and</li>
<li>replace <code>member #t result</code> by <code>every identity result</code> and</li>
<li>always take the first of the last winners.</li>
</ul>
]]></description>
</item>
<item>
<title>Day 5, Puzzle 1: Sidestep the vents</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-5-puzzle-1</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-5-puzzle-1</guid>
<pubDate>Mon, 06 Dec 2021 23:54:00 +0100</pubDate>

<description><![CDATA[<p>
Draw lines and find meeting points.
</p>

<div class="org-src-container">
<pre class="src src-dot"><code>0,9 -&gt; 5,9
8,0 -&gt; 0,8
9,4 -&gt; 3,4
2,2 -&gt; 2,1
7,0 -&gt; 7,4
6,4 -&gt; 2,0
0,9 -&gt; 2,9
3,4 -&gt; 1,4
0,0 -&gt; 8,8
5,5 -&gt; 8,2
</code></pre>
</div>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :26) cut
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :1) fold
<span style="color: #0000ff;">         ice-9</span> hash-table

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pixels-for-line</span> x0 y0 x1 y1
<span style="color: #0000ff;">  cond</span> <span style="color: #b22222;">;; </span><span style="color: #b22222;">only vertical and orthogonal lines</span>
<span style="color: #0000ff;">    {y0</span> = y1} 
<span style="color: #0000ff;">      map</span> (<span style="color: #0000ff;">cut</span> cons &lt;&gt; y0)
        <span style="color: #483d8b;">if</span> {x0 &lt; x1}<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">iota</span> (<span style="color: #0000ff;">+</span> <span style="color: #008b8b;">1</span> {x1 - x0}) x0
<span style="color: #0000ff;">                       iota</span> (<span style="color: #0000ff;">+</span> <span style="color: #008b8b;">1</span> {x0 - x1}) x1
<span style="color: #0000ff;">    {x0</span> = x1} 
<span style="color: #0000ff;">      map</span> (<span style="color: #0000ff;">cut</span> cons x0 &lt;&gt;)
        <span style="color: #483d8b;">if</span> {y0 &lt; y1}<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">iota</span> (<span style="color: #0000ff;">+</span> <span style="color: #008b8b;">1</span> {y1 - y0}) y0
<span style="color: #0000ff;">                       iota</span> (<span style="color: #0000ff;">+</span> <span style="color: #008b8b;">1</span> {y0 - y1}) y1
<span style="color: #0000ff;">    else</span> <span style="color: #008b8b;">'()</span>

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">line-coordinates</span> line
<span style="color: #0000ff;">  map</span> string-&gt;number<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-tokenize</span> line char-set:digit

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">hash-add1</span> key al
<span style="color: #0000ff;">  hash-set!</span> al key<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">+</span> <span style="color: #008b8b;">1</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">hash-ref</span> al key <span style="color: #008b8b;">0</span>
<span style="color: #a020f0;">  . </span>al

<span style="color: #483d8b;">define</span> port<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">open-input-file</span> <span style="color: #8b2252;">"advent-of-wisp-code-2021-d5p1-example-input.dot"</span>


<span style="color: #0000ff;">display</span>
<span style="color: #0000ff;">  hash-count</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;(key</span> value) {value &gt;= 2}
      <span style="color: #483d8b;">let</span> loop<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> coordinates<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">make-hash-table</span>
        <span style="color: #483d8b;">define</span> line<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">read-line</span> port
        <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">eof-object?</span> line
<span style="color: #a020f0;">          . </span>coordinates
<span style="color: #0000ff;">          loop</span>
<span style="color: #0000ff;">            fold</span> hash-add1 coordinates
<span style="color: #0000ff;">                 apply</span> pixels-for-line<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">line-coordinates</span> line

</code></pre>
</div>
]]></description>
</item>
<item>
<title>Day 5, Puzzle 2: Sidestep the vents diagonally</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-5-puzzle-2</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-5-puzzle-2</guid>
<pubDate>Mon, 06 Dec 2021 23:54:00 +0100</pubDate>

<description><![CDATA[<p>
Draw lines and find meeting points.
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :26) cut
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :1) fold
<span style="color: #0000ff;">         ice-9</span> hash-table
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pixels-for-line</span> x0 y0 x1 y1
<span style="color: #0000ff;">  cond</span> <span style="color: #b22222;">;; </span><span style="color: #b22222;">only vertical and orthogonal lines</span>
<span style="color: #0000ff;">    {y0</span> = y1} 
<span style="color: #0000ff;">      map</span> (<span style="color: #0000ff;">cut</span> cons &lt;&gt; y0)
        <span style="color: #483d8b;">if</span> {x0 &lt; x1}<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">iota</span> (<span style="color: #0000ff;">+</span> <span style="color: #008b8b;">1</span> {x1 - x0}) x0
<span style="color: #0000ff;">                       iota</span> (<span style="color: #0000ff;">+</span> <span style="color: #008b8b;">1</span> {x0 - x1}) x1
<span style="color: #0000ff;">    {x0</span> = x1} 
<span style="color: #0000ff;">      map</span> (<span style="color: #0000ff;">cut</span> cons x0 &lt;&gt;)
        <span style="color: #483d8b;">if</span> {y0 &lt; y1}<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">iota</span> (<span style="color: #0000ff;">+</span> <span style="color: #008b8b;">1</span> {y1 - y0}) y0
<span style="color: #0000ff;">                       iota</span> (<span style="color: #0000ff;">+</span> <span style="color: #008b8b;">1</span> {y0 - y1}) y1
<span style="color: #0000ff;">    else</span> 
<span style="color: #0000ff;">      map</span> cons
        <span style="color: #483d8b;">if</span> {x0 &lt; x1}<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">iota</span> (<span style="color: #0000ff;">+</span> <span style="color: #008b8b;">1</span> {x1 - x0}) x0
<span style="color: #0000ff;">                       iota</span> (<span style="color: #0000ff;">+</span> <span style="color: #008b8b;">1</span> {x0 - x1}) x0 <span style="color: #008b8b;">-1</span>
        <span style="color: #483d8b;">if</span> {y0 &lt; y1}<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">iota</span> (<span style="color: #0000ff;">+</span> <span style="color: #008b8b;">1</span> {y1 - y0}) y0
<span style="color: #0000ff;">                       iota</span> (<span style="color: #0000ff;">+</span> <span style="color: #008b8b;">1</span> {y0 - y1}) y0 <span style="color: #008b8b;">-1</span>

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">line-coordinates</span> line
<span style="color: #0000ff;">  map</span> string-&gt;number<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-tokenize</span> line char-set:digit
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">hash-add1</span> key al
<span style="color: #0000ff;">  hash-set!</span> al key<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">+</span> <span style="color: #008b8b;">1</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">hash-ref</span> al key <span style="color: #008b8b;">0</span>
<span style="color: #a020f0;">  . </span>al

<span style="color: #483d8b;">define</span> port<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">open-input-file</span> <span style="color: #8b2252;">"advent-of-wisp-code-2021-d5p1-example-input.dot"</span>
<span style="color: #0000ff;">display</span>
<span style="color: #0000ff;">  hash-count</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;(key</span> value) {value &gt;= 2}
      <span style="color: #483d8b;">let</span> loop<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> coordinates<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">make-hash-table</span>
        <span style="color: #483d8b;">define</span> line<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">read-line</span> port
        <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">eof-object?</span> line
<span style="color: #a020f0;">          . </span>coordinates
<span style="color: #0000ff;">          loop</span>
<span style="color: #0000ff;">            fold</span> hash-add1 coordinates
<span style="color: #0000ff;">                 apply</span> pixels-for-line<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">line-coordinates</span> line

</code></pre>
</div>
]]></description>
</item>
<item>
<title>Day 6, Puzzle 1: Model Exponential Fish</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-6-puzzle-1</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-6-puzzle-1</guid>
<pubDate>Mon, 06 Dec 2021 23:54:00 +0100</pubDate>

<description><![CDATA[<p>
Strange lanternfishes reproduce every 7 days, new fish initially
reproduce after 9 days. Model the population growth.
</p>

<p>
How many will there be <i>after 80 days</i>?
</p>

<p>
Input: The time to reproduce for each fish.
</p>

<div class="org-src-container">
<pre class="src src-csv"><code>3<span style="color: #a52a2a;">,</span>4<span style="color: #a52a2a;">,</span>3<span style="color: #a52a2a;">,</span>1<span style="color: #a52a2a;">,</span>2
</code></pre>
</div>

<p>
For this data format, a simplest possible csv parser is useful. I
could use <a href="https://github.com/artyom-poptsov/guile-dsv/">guile-dsv</a>, but I want to avoid libraries here to you can run
the code without installing anything but <a href="https://www.gnu.org/software/guile/">Guile</a> and <a href="https://www.draketo.de/software/wisp.html">wisp</a>. So here is
the simplest tool to read commaseparated numbers from a line of text:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">snippet: {{{read-numbers-from-csv-line}}}</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">read-numbers-from-csv-line</span> filename
  <span style="color: #483d8b;">let</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> port<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">open-input-file</span> filename
    <span style="color: #483d8b;">define</span> res<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> string-&gt;number<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-split</span> (<span style="color: #0000ff;">read-line</span> port) <span style="color: #008b8b;">#\,</span>
<span style="color: #0000ff;">    close</span> port
<span style="color: #a020f0;">    . </span>res
</code></pre>
</div>

<p>
For 80 days, I can use a naive approach and simply keep a list of
numbers with the reproduction time.
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">srfi</span> :1) fold
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line
{{{read-numbers-from-csv-line}}}

<span style="color: #483d8b;">define</span> input
<span style="color: #0000ff;">  read-numbers-from-csv-line</span>
<span style="color: #a020f0;">    . </span><span style="color: #8b2252;">"advent-of-wisp-code-2021-d6p1-example-input.dat"</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">reproduce</span> time-to-reproduce prev
  <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">zero?</span> time-to-reproduce
<span style="color: #0000ff;">       cons</span> <span style="color: #008b8b;">8</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cons</span> <span style="color: #008b8b;">6</span> prev
<span style="color: #0000ff;">       cons</span> {time-to-reproduce - 1} prev

<span style="color: #0000ff;">display</span>
<span style="color: #0000ff;"> length</span>
  <span style="color: #483d8b;">let</span> rep<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">(steps</span> <span style="color: #008b8b;">80</span>) (<span style="color: #0000ff;">swarm</span> input)
    <span style="color: #483d8b;">if</span> (<span style="color: #0000ff;">zero?</span> steps) swarm
<span style="color: #0000ff;">      rep</span> {steps - 1}<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">fold</span> reproduce <span style="color: #008b8b;">'()</span> swarm
</code></pre>
</div>
]]></description>
</item>
<item>
<title>Day 6, Puzzle 2: Model Exponential Fish in Memory</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-6-puzzle-2</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-6-puzzle-2</guid>
<pubDate>Mon, 06 Dec 2021 23:54:00 +0100</pubDate>

<description><![CDATA[<p>
Now the goal is 256 days. That kills my memory for sure. Need a tighter
datastructure. Let’s use the keys for the lifetimes. The keys are
contiguous integers, so why not a vector?
</p>

<div class="org-src-container">
<pre class="src src-csv"><code>3<span style="color: #a52a2a;">,</span>4<span style="color: #a52a2a;">,</span>3<span style="color: #a52a2a;">,</span>1<span style="color: #a52a2a;">,</span>2
</code></pre>
</div>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">srfi</span> :1) fold
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line

{{{read-numbers-from-csv-line}}}

<span style="color: #483d8b;">define</span> input
<span style="color: #0000ff;">  read-numbers-from-csv-line</span>
<span style="color: #a020f0;">    . </span><span style="color: #8b2252;">"advent-of-wisp-code-2021-d6p1-example-input.dat"</span>

<span style="color: #483d8b;">define</span> swarm-lifetime-counts
  <span style="color: #483d8b;">let</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> swarm<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">make-vector</span> <span style="color: #008b8b;">9</span> <span style="color: #008b8b;">0</span>
<span style="color: #0000ff;">    for-each</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;</span> (<span style="color: #0000ff;">x</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">vector-set!</span> swarm x<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">+</span> <span style="color: #008b8b;">1</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">vector-ref</span> swarm x
<span style="color: #a020f0;">      . </span>input
<span style="color: #a020f0;">    . </span>swarm

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">reproduce</span> swarm
  <span style="color: #483d8b;">define</span> reproducing<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">vector-ref</span> swarm <span style="color: #008b8b;">0</span>
  <span style="color: #b22222;">;; </span><span style="color: #b22222;">reduce all lifetimes by 1</span>
<span style="color: #0000ff;">  for-each</span>
<span style="color: #0000ff;">    &#955;</span> (<span style="color: #0000ff;">lifetime</span>)
<span style="color: #0000ff;">      vector-set!</span> swarm {lifetime - 1}<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">vector-ref</span> swarm lifetime
<span style="color: #0000ff;">    iota</span> <span style="color: #008b8b;">8</span> <span style="color: #008b8b;">1</span>
  <span style="color: #b22222;">;; </span><span style="color: #b22222;">add the reproducing to lifetime 6 and 8</span>
<span style="color: #0000ff;">  vector-set!</span> swarm <span style="color: #008b8b;">6</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">+</span> reproducing<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">vector-ref</span> swarm <span style="color: #008b8b;">6</span>
<span style="color: #0000ff;">  vector-set!</span> swarm <span style="color: #008b8b;">8</span> reproducing
<span style="color: #a020f0;">  . </span>swarm

<span style="color: #0000ff;">display</span>
<span style="color: #0000ff;">  apply</span> +
<span style="color: #0000ff;">    vector-&gt;list</span>
      <span style="color: #483d8b;">let</span> rep<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">(steps</span> <span style="color: #008b8b;">256</span>) (<span style="color: #0000ff;">swarm</span> swarm-lifetime-counts)
        <span style="color: #483d8b;">if</span> (<span style="color: #0000ff;">zero?</span> steps) swarm
<span style="color: #0000ff;">          rep</span> {steps - 1}<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">reproduce</span> swarm
</code></pre>
</div>

<p>
Since the fish with the real data are in the trillions, no way I could
have done this with the plain list. Each pointer in a linked list
needs around 8 byte; just the datastructure would have eaten all my
memory many times over. Even a naively optimized tight array with
3-bit-numbers would not have enabled that.
</p>

<p>
With the new index-counting vector datastructure though, I can easily
do 2560 steps. With the example data, the resulting number has 98
digits. 256000 steps take about a second to compute a number with 9687
digits.
</p>

<p>
Computers are fast.
</p>
]]></description>
</item>
<item>
<title>Day 7, Puzzle 1: Align Fuel Constrained Crab Guns</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-7-puzzle-1</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-7-puzzle-1</guid>
<pubDate>Thu, 09 Dec 2021 20:15:00 +0100</pubDate>

<description><![CDATA[<p>
Crabs come to blast a path into a cave. You must align them: Find the
positions where they need to move the least amount of steps so their
guns can interlock into one big gun.
</p>

<div class="org-src-container">
<pre class="src src-csv"><code>16<span style="color: #a52a2a;">,</span>1<span style="color: #a52a2a;">,</span>2<span style="color: #a52a2a;">,</span>0<span style="color: #a52a2a;">,</span>4<span style="color: #a52a2a;">,</span>2<span style="color: #a52a2a;">,</span>7<span style="color: #a52a2a;">,</span>1<span style="color: #a52a2a;">,</span>2<span style="color: #a52a2a;">,</span>14
</code></pre>
</div>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :26) cut
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :1) list-index list-ref

{{{read-numbers-from-csv-line}}}

<span style="color: #483d8b;">define</span> crabs
<span style="color: #0000ff;">  read-numbers-from-csv-line</span>
<span style="color: #a020f0;">    . </span><span style="color: #8b2252;">"advent-of-wisp-code-2021-d7p1-example-input.dat"</span>

<span style="color: #483d8b;">define</span> min-position<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> min crabs
<span style="color: #483d8b;">define</span> max-position<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> max crabs

<span style="color: #483d8b;">define</span> possible-positions
<span style="color: #0000ff;">  iota</span> (<span style="color: #0000ff;">+</span> <span style="color: #008b8b;">1</span> {max-position - min-position}) min-position

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">fuel-cost</span> target-position crabs
  <span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">fuel-cost</span> crab 
<span style="color: #0000ff;">    abs</span> {crab - target-position}
<span style="color: #0000ff;">  apply</span> +<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> fuel-cost crabs

<span style="color: #483d8b;">define</span> costs<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> (<span style="color: #0000ff;">cut</span> fuel-cost &lt;&gt; crabs) possible-positions
<span style="color: #483d8b;">define</span> min-cost<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> min costs
<span style="color: #483d8b;">define</span> ideal-position
<span style="color: #0000ff;">  list-ref</span> possible-positions
<span style="color: #0000ff;">    list-index</span> (<span style="color: #0000ff;">cut</span> equal? min-cost &lt;&gt;) costs

<span style="color: #0000ff;">display</span> min-cost
</code></pre>
</div>
]]></description>
</item>
<item>
<title>Day 7, Puzzle 2: Align Stingy Crab Guns</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-7-puzzle-2</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-7-puzzle-2</guid>
<pubDate>Thu, 09 Dec 2021 20:15:00 +0100</pubDate>

<description><![CDATA[<p>
Movement cost now increases by one per step. Step 1 is 1. Step 2 costs 2, so it is 3. Formula: (step * (step + 1)) / 2
</p>

<div class="org-src-container">
<pre class="src src-csv"><code>16<span style="color: #a52a2a;">,</span>1<span style="color: #a52a2a;">,</span>2<span style="color: #a52a2a;">,</span>0<span style="color: #a52a2a;">,</span>4<span style="color: #a52a2a;">,</span>2<span style="color: #a52a2a;">,</span>7<span style="color: #a52a2a;">,</span>1<span style="color: #a52a2a;">,</span>2<span style="color: #a52a2a;">,</span>14
</code></pre>
</div>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :26) cut
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :1) list-index list-ref

{{{read-numbers-from-csv-line}}}

<span style="color: #483d8b;">define</span> crabs
<span style="color: #0000ff;">  read-numbers-from-csv-line</span>
<span style="color: #a020f0;">    . </span><span style="color: #8b2252;">"advent-of-wisp-code-2021-d7p1-example-input.dat"</span>

<span style="color: #483d8b;">define</span> min-position<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> min crabs
<span style="color: #483d8b;">define</span> max-position<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> max crabs

<span style="color: #483d8b;">define</span> possible-positions
<span style="color: #0000ff;">  iota</span> (<span style="color: #0000ff;">+</span> <span style="color: #008b8b;">1</span> {max-position - min-position}) min-position

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">fuel-cost</span> target-position crabs
  <span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">distance</span> crab 
<span style="color: #0000ff;">    abs</span> {crab - target-position}
  <span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cost</span> crab
    <span style="color: #483d8b;">define</span> dist<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">distance</span> crab
<span style="color: #0000ff;">    *</span> 1/2 dist {dist + 1}
<span style="color: #0000ff;">  apply</span> +<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> cost crabs

<span style="color: #483d8b;">define</span> costs<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> (<span style="color: #0000ff;">cut</span> fuel-cost &lt;&gt; crabs) possible-positions
<span style="color: #483d8b;">define</span> min-cost<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> min costs
<span style="color: #483d8b;">define</span> ideal-position
<span style="color: #0000ff;">  list-ref</span> possible-positions
<span style="color: #0000ff;">    list-index</span> (<span style="color: #0000ff;">cut</span> equal? min-cost &lt;&gt;) costs

<span style="color: #0000ff;">display</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">format</span> <span style="color: #008b8b;">#f</span> <span style="color: #8b2252;">"position: ~a, cost: ~a"</span> ideal-position min-cost
</code></pre>
</div>
]]></description>
</item>
<item>
<title>Day 8, Puzzle 1: Which numbers are shown?</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-8-puzzle-1</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-8-puzzle-1</guid>
<pubDate>Wed, 15 Dec 2021 00:26:00 +0100</pubDate>

<description><![CDATA[<p>
I’m late on this, because a brief solution wasn’t directly obvious and
I didn’t have much time.
</p>

<p>
I have 10 patterns and 4 displays. Four numbers use a unique number of connections:
</p>

<ul class="org-ul">
<li>1: 2</li>
<li>4: 4</li>
<li>7: 3</li>
<li>8: 7</li>
</ul>

<p>
So basically I just need to count occurence of length of strings.
</p>

<p>
Input:
</p>
<div class="org-src-container">
<pre class="src src-csv"><code>be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe cefdb cefbgd gcbe
edbfga begcd cbg gc gcadebf fbgde acbgfd abcde gfcbed gfec | fcgedb cgb dgebacf gc
fgaebd cg bdaec gdafb agbcfd gdcbef bgcad gfac gcb cdgabef | cg cg fdcagb cbg
fbegcd cbd adcefb dageb afcb bc aefdc ecdab fgdeca fcdbega | efabcd cedba gadfec cb
aecbfdg fbg gf bafeg dbefa fcge gcbea fcaegb dgceab fcbdga | gecf egdcabf bgf bfgea
fgeab ca afcebg bdacfeg cfaedg gcfdb baec bfadeg bafgc acf | gebdcfa ecba ca fadegcb
dbcfg fgd bdegcaf fgec aegbdf ecdfab fbedc dacgb gdcebf gf | cefg dcbef fcge gbcadfe
bdfegc cbegaf gecbf dfcage bdacg ed bedf ced adcbefg gebcd | ed bcgafe cdgba cbgef
egadfb cdbfeg cegd fecab cgb gbdefca cg fgcdab egfdb bfceg | gbdfcae bgc cg cgb
gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc | fgae cfgab fg bagce
</code></pre>
</div>
<p>
Code:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line
<span style="color: #0000ff;">         srfi</span> :9 records
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :26) cut
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :1) second
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">split-result-into-length</span> line
<span style="color: #0000ff;">  map</span> string-length
<span style="color: #0000ff;">    string-tokenize</span>
<span style="color: #0000ff;">      second</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-split</span> line <span style="color: #008b8b;">#\|</span>
<span style="color: #a020f0;">      . </span>char-set:letter

{{{map-over-lines}}}

<span style="color: #483d8b;">define</span> input
<span style="color: #0000ff;">  apply</span> append
<span style="color: #0000ff;">    map-over-lines</span> split-result-into-length
<span style="color: #a020f0;">      . </span><span style="color: #8b2252;">"advent-of-wisp-code-2021-d8p1-example-input.dat"</span>

<span style="color: #483d8b;">define</span> counter<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">make-vector</span> <span style="color: #008b8b;">8</span> <span style="color: #008b8b;">0</span>

<span style="color: #0000ff;">for-each</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;(len)</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">vector-set!</span> counter len<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">+</span> <span style="color: #008b8b;">1</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">vector-ref</span> counter len
<span style="color: #a020f0;">         . </span>input  

<span style="color: #0000ff;">display</span>
<span style="color: #0000ff;">  apply</span> +
<span style="color: #0000ff;">    map</span> (<span style="color: #0000ff;">cut</span> vector-ref counter &lt;&gt;)
<span style="color: #0000ff;">      list</span> <span style="color: #008b8b;">2</span> <span style="color: #008b8b;">4</span> <span style="color: #008b8b;">3</span> <span style="color: #008b8b;">7</span>
</code></pre>
</div>
]]></description>
</item>
<item>
<title>Day 8, Puzzle 2: Which numbers are shown?</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-8-puzzle-2</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-8-puzzle-2</guid>
<pubDate>Thu, 16 Dec 2021 02:20:00 +0100</pubDate>

<description><![CDATA[<p>
Now do the full mapping.
</p>

<p>
Use the left-hand patterns to recover the configuration.
</p>


<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line
<span style="color: #0000ff;">         srfi</span> :9 records
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :26) cut
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :1) first second fold assoc
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">rnrs</span> lists (<span style="color: #0000ff;">6</span>)) find
<span style="color: #b22222;">;;; </span><span style="color: #b22222;">problem definition</span>
<span style="color: #b22222;">;; </span><span style="color: #b22222;">the numbers with letters for fields. The fields got scrambled.</span>
<span style="color: #b22222;">;;   </span><span style="color: #b22222;">0:      1:      2:      3:      4:</span>
<span style="color: #b22222;">;;  </span><span style="color: #b22222;">aaaa    ....    aaaa    aaaa    ....</span>
<span style="color: #b22222;">;; </span><span style="color: #b22222;">b    c  .    c  .    c  .    c  b    c</span>
<span style="color: #b22222;">;; </span><span style="color: #b22222;">b    c  .    c  .    c  .    c  b    c</span>
<span style="color: #b22222;">;;  </span><span style="color: #b22222;">....    ....    dddd    dddd    dddd</span>
<span style="color: #b22222;">;; </span><span style="color: #b22222;">e    f  .    f  e    .  .    f  .    f</span>
<span style="color: #b22222;">;; </span><span style="color: #b22222;">e    f  .    f  e    .  .    f  .    f</span>
<span style="color: #b22222;">;;  </span><span style="color: #b22222;">gggg    ....    gggg    gggg    ....  </span>
<span style="color: #b22222;">;; </span>
<span style="color: #b22222;">;;   </span><span style="color: #b22222;">5:      6:      7:      8:      9:</span>
<span style="color: #b22222;">;;  </span><span style="color: #b22222;">aaaa    aaaa    aaaa    aaaa    aaaa</span>
<span style="color: #b22222;">;; </span><span style="color: #b22222;">b    .  b    .  .    c  b    c  b    c</span>
<span style="color: #b22222;">;; </span><span style="color: #b22222;">b    .  b    .  .    c  b    c  b    c</span>
<span style="color: #b22222;">;;  </span><span style="color: #b22222;">dddd    dddd    ....    dddd    dddd</span>
<span style="color: #b22222;">;; </span><span style="color: #b22222;">.    f  e    f  .    f  e    f  .    f</span>
<span style="color: #b22222;">;; </span><span style="color: #b22222;">.    f  e    f  .    f  e    f  .    f</span>
<span style="color: #b22222;">;;  </span><span style="color: #b22222;">gggg    gggg    ....    gggg    gggg  </span>

<span style="color: #b22222;">;; </span><span style="color: #b22222;">define number-by-length deciders</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">1?</span> string
<span style="color: #0000ff;">  =</span> <span style="color: #008b8b;">2</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-length</span> string
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">7?</span> string
<span style="color: #0000ff;">  =</span> <span style="color: #008b8b;">3</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-length</span> string
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">4?</span> string
<span style="color: #0000ff;">  =</span> <span style="color: #008b8b;">4</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-length</span> string
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">8?</span> string
<span style="color: #0000ff;">  =</span> <span style="color: #008b8b;">7</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-length</span> string
<span style="color: #b22222;">;; </span><span style="color: #b22222;">6 numbers share lengths</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">2-or-3-or-5?</span> string
<span style="color: #0000ff;">  =</span> <span style="color: #008b8b;">5</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-length</span> string
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">0-or-6-or-9?</span> string
<span style="color: #0000ff;">  =</span> <span style="color: #008b8b;">6</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-length</span> string


<span style="color: #b22222;">;;; </span><span style="color: #b22222;">get the input</span>
<span style="color: #b22222;">;; </span><span style="color: #b22222;">returns (pattern-part result-part)</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">split-into-strings</span> line
<span style="color: #0000ff;">  map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cut</span> string-tokenize &lt;&gt; char-set:letter
<span style="color: #0000ff;">    string-split</span> line #\|

{{{map-over-lines}}}

<span style="color: #483d8b;">define</span> input-strings
<span style="color: #0000ff;">  map-over-lines</span> split-into-strings
<span style="color: #a020f0;">    . </span><span style="color: #8b2252;">"advent-of-wisp-code-2021-d8p1-example-input.dat"</span>

<span style="color: #483d8b;">define</span> input-charsets
<span style="color: #0000ff;">  map</span>
<span style="color: #0000ff;">    &#955;(line)</span>
<span style="color: #0000ff;">      map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;(x)</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> string-&gt;char-set x
<span style="color: #a020f0;">          . </span>line
<span style="color: #a020f0;">    . </span>input-strings


<span style="color: #b22222;">;;; </span><span style="color: #b22222;">Calculate and apply the de-scrambling and calculation per line</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">process-one-line</span> line-strings line-charsets
  <span style="color: #b22222;">;; </span><span style="color: #b22222;">identify the char-sets for digits of unique length</span>
  <span style="color: #483d8b;">define</span> pattern-strings
<span style="color: #0000ff;">    first</span> line-strings
  <span style="color: #483d8b;">define</span> result-charsets
<span style="color: #0000ff;">    second</span> line-charsets
  <span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">find-matching-charsets</span> string-matches? pattern-strings
<span style="color: #0000ff;">           fold</span>
<span style="color: #0000ff;">             &#955;(string</span> prev)
<span style="color: #0000ff;">               append</span>
                 <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-matches?</span> string
<span style="color: #0000ff;">                   list</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-&gt;char-set</span> string
<span style="color: #a020f0;">                   . </span><span style="color: #008b8b;">'()</span>
<span style="color: #a020f0;">                 . </span>prev
<span style="color: #a020f0;">             . </span><span style="color: #008b8b;">'()</span> pattern-strings
  <span style="color: #483d8b;">define</span> one<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">first</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">find-matching-charsets</span> 1? pattern-strings
  <span style="color: #483d8b;">define</span> four<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">first</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">find-matching-charsets</span> 4? pattern-strings
  <span style="color: #483d8b;">define</span> seven<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">first</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">find-matching-charsets</span> 7? pattern-strings
  <span style="color: #483d8b;">define</span> eight<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">first</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">find-matching-charsets</span> 8? pattern-strings
  <span style="color: #483d8b;">define</span> zero-or-six-or-nine
<span style="color: #0000ff;">    find-matching-charsets</span> 0-or-6-or-9? pattern-strings

  <span style="color: #483d8b;">define</span> six
<span style="color: #0000ff;">    find</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;(x)</span><span style="color: #a020f0;"> : </span><span style="color: #483d8b;">not</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">char-set&lt;=</span> one x
<span style="color: #a020f0;">         . </span>zero-or-six-or-nine
  <span style="color: #483d8b;">define</span> zero-or-nine
<span style="color: #0000ff;">    filter</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;(x)</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">char-set&lt;=</span> one x
<span style="color: #a020f0;">         . </span>zero-or-six-or-nine
  <span style="color: #483d8b;">define</span> nine
<span style="color: #0000ff;">    find</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;(x)</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">char-set&lt;=</span> four x
<span style="color: #a020f0;">      . </span>zero-or-nine
  <span style="color: #483d8b;">define</span> zero
<span style="color: #0000ff;">    find</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;(x)</span><span style="color: #a020f0;"> : </span><span style="color: #483d8b;">not</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">char-set&lt;=</span> four x
<span style="color: #a020f0;">      . </span>zero-or-nine
  <span style="color: #483d8b;">define</span> two-or-three-or-five
<span style="color: #0000ff;">    find-matching-charsets</span> 2-or-3-or-5? pattern-strings
  <span style="color: #483d8b;">define</span> three
<span style="color: #0000ff;">    find</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;(x)</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">char-set&lt;=</span> one x
<span style="color: #a020f0;">         . </span>two-or-three-or-five
  <span style="color: #483d8b;">define</span> five
<span style="color: #0000ff;">    find</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;(x)</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">char-set&lt;=</span> x nine
<span style="color: #0000ff;">         delete</span> three two-or-three-or-five
  <span style="color: #483d8b;">define</span> two
<span style="color: #0000ff;">    first</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">delete</span> five<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">delete</span> three two-or-three-or-five

  <span style="color: #483d8b;">define</span> charset-to-number
<span style="color: #0000ff;">    list</span>
<span style="color: #0000ff;">      cons</span> zero <span style="color: #008b8b;">0</span>
<span style="color: #0000ff;">      cons</span> one <span style="color: #008b8b;">1</span>
<span style="color: #0000ff;">      cons</span> two <span style="color: #008b8b;">2</span>
<span style="color: #0000ff;">      cons</span> three <span style="color: #008b8b;">3</span>
<span style="color: #0000ff;">      cons</span> four <span style="color: #008b8b;">4</span>
<span style="color: #0000ff;">      cons</span> five <span style="color: #008b8b;">5</span>
<span style="color: #0000ff;">      cons</span> six <span style="color: #008b8b;">6</span>
<span style="color: #0000ff;">      cons</span> seven <span style="color: #008b8b;">7</span>
<span style="color: #0000ff;">      cons</span> eight <span style="color: #008b8b;">8</span>
<span style="color: #0000ff;">      cons</span> nine <span style="color: #008b8b;">9</span>

<span style="color: #0000ff;">  string-&gt;number</span>
<span style="color: #0000ff;">    string-join</span>
<span style="color: #0000ff;">      map</span> number-&gt;string
<span style="color: #0000ff;">        map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;(x)</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cdr</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">assoc</span> x charset-to-number char-set=
<span style="color: #a020f0;">            . </span>result-charsets
<span style="color: #a020f0;">      . </span><span style="color: #8b2252;">""</span>

<span style="color: #0000ff;">write</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> +<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> process-one-line input-strings input-charsets
</code></pre>
</div>

<p>
This one was long, far longer than I would have liked. And with much
more logic coming in from me instead of the program. I wonder if
micro-/minikanren or Prolog would provide for a nicer solution.
</p>
]]></description>
</item>
<item>
<title>Day 9, Puzzle 1: Avoid smoke-sinks</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-9-puzzle-1</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-9-puzzle-1</guid>
<pubDate>Thu, 16 Dec 2021 02:20:00 +0100</pubDate>

<description><![CDATA[<p>
Find low points in height-map.
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">2199943210</span>
<span style="color: #0000ff;">3987894921</span>
<span style="color: #0000ff;">9856789892</span>
<span style="color: #0000ff;">8767896789</span>
<span style="color: #0000ff;">9899965678</span>
</code></pre>
</div>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> pretty-print) pretty-print
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :1) fold

{{{map-over-lines}}}

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-letters-&gt;numbers</span> line
<span style="color: #a020f0;">    . </span><span style="color: #8b2252;">"turn every letter in the string into the base10 number it represents"</span>
<span style="color: #0000ff;">    map</span> string-&gt;number<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> string<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-&gt;list</span> line

<span style="color: #483d8b;">define</span> input
<span style="color: #0000ff;">  list-&gt;vector</span>
<span style="color: #0000ff;">    map-over-lines</span>
<span style="color: #0000ff;">      &#955;</span> (<span style="color: #0000ff;">line</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">list-&gt;vector</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-letters-&gt;numbers</span> line
<span style="color: #a020f0;">      . </span><span style="color: #8b2252;">"advent-of-wisp-code-2021-d9p1-example-input.dat"</span>

<span style="color: #483d8b;">define</span> len-y<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">1-</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">vector-length</span> input
<span style="color: #483d8b;">define</span> len-x<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">1-</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">vector-length</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">vector-ref</span> input <span style="color: #008b8b;">0</span>

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">at</span> vec x y
<span style="color: #0000ff;">  vector-ref</span> (<span style="color: #0000ff;">vector-ref</span> input y) x

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">low-point?</span> input x y
  <span style="color: #483d8b;">define</span> up<span style="color: #a020f0;"> : </span><span style="color: #483d8b;">and</span> {y &gt; 0} {y - 1}
  <span style="color: #483d8b;">define</span> down<span style="color: #a020f0;"> : </span><span style="color: #483d8b;">and</span> {y &lt; len-y} {y + 1}
  <span style="color: #483d8b;">define</span> left<span style="color: #a020f0;"> : </span><span style="color: #483d8b;">and</span> {x &gt; 0} {x - 1}
  <span style="color: #483d8b;">define</span> right<span style="color: #a020f0;"> : </span><span style="color: #483d8b;">and</span> {x &lt; len-x} {x + 1}
  <span style="color: #483d8b;">define</span> val<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">at</span> input x y
  <span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">y-lowerequal</span> y
<span style="color: #0000ff;">    &gt;=</span> val<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">at</span> input x y
  <span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">x-lowerequal</span> x
<span style="color: #0000ff;">    &gt;=</span> val<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">at</span> input x y
  <span style="color: #483d8b;">not</span> <span style="color: #b22222;">;; </span><span style="color: #b22222;">no accessible point may be lower or equal</span>
   <span style="color: #483d8b;">or</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">and=&gt;</span> up y-lowerequal
<span style="color: #0000ff;">        and=&gt;</span> down y-lowerequal
<span style="color: #0000ff;">        and=&gt;</span> left x-lowerequal
<span style="color: #0000ff;">        and=&gt;</span> right x-lowerequal

<span style="color: #483d8b;">define</span> risk-levels
<span style="color: #0000ff;"> map</span>
<span style="color: #0000ff;">  &#955;(y)</span>
<span style="color: #0000ff;">    map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;(x)</span><span style="color: #a020f0;"> : </span><span style="color: #483d8b;">if</span> (<span style="color: #0000ff;">low-point?</span> input x y) (<span style="color: #0000ff;">+</span> <span style="color: #008b8b;">1</span> (<span style="color: #0000ff;">at</span> input x y)) <span style="color: #008b8b;">0</span>
<span style="color: #0000ff;">             iota</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">+</span> <span style="color: #008b8b;">1</span> len-x
<span style="color: #0000ff;">  iota</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">+</span> <span style="color: #008b8b;">1</span> len-y

<span style="color: #0000ff;">pretty-print</span> 
<span style="color: #0000ff;">  map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;(x)</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-join</span> (<span style="color: #0000ff;">map</span> number-&gt;string x) <span style="color: #8b2252;">""</span>
<span style="color: #a020f0;">    . </span>risk-levels

<span style="color: #0000ff;">pretty-print</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> +<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> (<span style="color: #0000ff;">&#955;(row</span>) (<span style="color: #0000ff;">apply</span> + row)) risk-levels
</code></pre>
</div>
]]></description>
</item>
<item>
<title>Day 9, Puzzle 2: Discover Smoke Lakes</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-9-puzzle-2</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-9-puzzle-2</guid>
<pubDate>Sat, 18 Dec 2021 02:04:00 +0100</pubDate>

<description><![CDATA[<p>
Expand each low-point while the ground gets higher, except if it reaches 9.
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> pretty-print) pretty-print
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :1) fold every any lset-difference delete-duplicates take
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :26) cut
<span style="color: #0000ff;">         ice-9</span> string-fun

{{{map-over-lines}}}

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-letters-&gt;numbers</span> line
<span style="color: #a020f0;">    . </span><span style="color: #8b2252;">"turn every letter in the string into the base10 number it represents"</span>
<span style="color: #0000ff;">    map</span> string-&gt;number<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> string<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-&gt;list</span> line

<span style="color: #483d8b;">define</span> input
<span style="color: #0000ff;">  list-&gt;vector</span>
<span style="color: #0000ff;">    map-over-lines</span>
<span style="color: #0000ff;">      &#955;</span> (<span style="color: #0000ff;">line</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">list-&gt;vector</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-letters-&gt;numbers</span> line
<span style="color: #a020f0;">      . </span><span style="color: #8b2252;">"advent-of-wisp-code-2021-d9p1-example-input.dat"</span>

<span style="color: #483d8b;">define</span> len-y<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">1-</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">vector-length</span> input
<span style="color: #483d8b;">define</span> len-x<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">1-</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">vector-length</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">vector-ref</span> input <span style="color: #008b8b;">0</span>

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">at</span> vec x y
<span style="color: #0000ff;">  vector-ref</span> (<span style="color: #0000ff;">vector-ref</span> input y) x

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">around</span> x y
<span style="color: #a020f0;">  . </span><span style="color: #8b2252;">"Get all points around the coordinate"</span>
  <span style="color: #483d8b;">define</span> up<span style="color: #a020f0;"> : </span><span style="color: #483d8b;">and</span> {y &gt; 0} {y - 1}
  <span style="color: #483d8b;">define</span> down<span style="color: #a020f0;"> : </span><span style="color: #483d8b;">and</span> {y &lt; len-y} {y + 1}
  <span style="color: #483d8b;">define</span> left<span style="color: #a020f0;"> : </span><span style="color: #483d8b;">and</span> {x &gt; 0} {x - 1}
  <span style="color: #483d8b;">define</span> right<span style="color: #a020f0;"> : </span><span style="color: #483d8b;">and</span> {x &lt; len-x} {x + 1}
<span style="color: #0000ff;">  delete</span> <span style="color: #008b8b;">#f</span>
<span style="color: #0000ff;">    list</span>
      <span style="color: #483d8b;">and</span> up<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cons</span> x up
      <span style="color: #483d8b;">and</span> down<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cons</span> x down
      <span style="color: #483d8b;">and</span> left<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cons</span> left y
      <span style="color: #483d8b;">and</span> right<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cons</span> right y

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">low-point?</span> input x y known
  <span style="color: #483d8b;">define</span> val<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">at</span> input x y
  <span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">part-of-area?</span> x y
    <span style="color: #483d8b;">or</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">member</span> (<span style="color: #0000ff;">cons</span> x y) known
<span style="color: #0000ff;">      &lt;</span> val<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">at</span> input x y
  <span style="color: #483d8b;">and</span> {val &lt; 9}
<span style="color: #0000ff;">    every</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;(point)</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">part-of-area?</span> (<span style="color: #0000ff;">car</span> point) (<span style="color: #0000ff;">cdr</span> point)
<span style="color: #0000ff;">        around</span> x y

<span style="color: #483d8b;">define</span> low-points
<span style="color: #0000ff;">  filter</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;(x)</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">low-point?</span> input (<span style="color: #0000ff;">car</span> x) (<span style="color: #0000ff;">cdr</span> x) <span style="color: #008b8b;">'()</span>
<span style="color: #0000ff;">    apply</span> append
<span style="color: #0000ff;">      map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;(y)</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> (<span style="color: #0000ff;">cut</span> cons &lt;&gt; y)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">iota</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">+</span> <span style="color: #008b8b;">1</span> len-x
<span style="color: #0000ff;">        iota</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">+</span> <span style="color: #008b8b;">1</span> len-y

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">next</span> x y known
  <span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">open?</span> point
    <span style="color: #483d8b;">and</span><span style="color: #a020f0;"> : </span><span style="color: #483d8b;">not</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">member</span> point known
<span style="color: #a020f0;">        . </span>point
<span style="color: #0000ff;">  delete</span> <span style="color: #008b8b;">#f</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> open?<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">around</span> x y

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">expand-area</span> area
  <span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">expands-basin?</span> val new
    <span style="color: #483d8b;">define</span> newval<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">at</span> input (<span style="color: #0000ff;">car</span> new) (<span style="color: #0000ff;">cdr</span> new)
<span style="color: #0000ff;">    &lt;</span> val newval <span style="color: #008b8b;">9</span>    
  <span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">expand-point</span> point
    <span style="color: #483d8b;">define</span> val<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">at</span> input (<span style="color: #0000ff;">car</span> point) (<span style="color: #0000ff;">cdr</span> point)
<span style="color: #0000ff;">    cons</span> point
<span style="color: #0000ff;">      filter</span> (<span style="color: #0000ff;">cut</span> expands-basin? val &lt;&gt;)
<span style="color: #0000ff;">        next</span> (<span style="color: #0000ff;">car</span> point) (<span style="color: #0000ff;">cdr</span> point) area
<span style="color: #0000ff;">  delete-duplicates</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> append<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> expand-point area

<span style="color: #483d8b;">define</span> areas
  <span style="color: #483d8b;">let</span> loop<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> areas<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> list low-points
    <span style="color: #483d8b;">define</span> open-points
<span style="color: #0000ff;">      lset-difference</span> equal?
<span style="color: #0000ff;">        apply</span> append
<span style="color: #0000ff;">          map</span> expand-area areas
<span style="color: #0000ff;">        apply</span> append areas
    <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">null?</span> open-points
<span style="color: #a020f0;">       . </span>areas
<span style="color: #0000ff;">       loop</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> expand-area areas


<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">basin-value</span> x y
    <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">any</span> identity<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> (<span style="color: #0000ff;">cut</span> member (<span style="color: #0000ff;">cons</span> x y) &lt;&gt;) areas
<span style="color: #0000ff;">       at</span> input x y
<span style="color: #a020f0;">       . </span><span style="color: #008b8b;">0</span>

<span style="color: #483d8b;">define</span> area-levels
<span style="color: #0000ff;"> map</span>
<span style="color: #0000ff;">  &#955;(y)</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> (<span style="color: #0000ff;">cut</span> basin-value &lt;&gt; y)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">iota</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">+</span> <span style="color: #008b8b;">1</span> len-x
<span style="color: #0000ff;">  iota</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">+</span> <span style="color: #008b8b;">1</span> len-y

<span style="color: #0000ff;">pretty-print</span> 
<span style="color: #0000ff;">  map</span>
<span style="color: #0000ff;">    &#955;(x)</span>
<span style="color: #0000ff;">      string-replace-substring</span>
<span style="color: #0000ff;">        string-join</span> (<span style="color: #0000ff;">map</span> number-&gt;string x) <span style="color: #8b2252;">""</span>
<span style="color: #a020f0;">        . </span><span style="color: #8b2252;">"0"</span> <span style="color: #8b2252;">" "</span>
<span style="color: #a020f0;">    . </span>area-levels

<span style="color: #0000ff;">pretty-print</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> *<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">take</span> (<span style="color: #0000ff;">sort</span> (<span style="color: #0000ff;">map</span> length areas) &gt;) <span style="color: #008b8b;">3</span>
</code></pre>
</div>

<p>
This is much too long for my taste, but I don’t see how to make it shorter.
</p>
]]></description>
</item>
<item>
<title>Day 10, Puzzle 1: Pick Wrongly Paired Parens</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-10-puzzle-1</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-10-puzzle-1</guid>
<pubDate>Sun, 19 Dec 2021 04:23:00 +0100</pubDate>

<description><![CDATA[<p>
Input:
</p>

<div class="org-src-container">
<pre class="src src-scheme"><code>[({(&lt;(())[]&gt;[[{[]{&lt;()<span style="color: #228b22;">&lt;&gt;&gt;</span>
[(()[&lt;&gt;])]({[&lt;{&lt;&lt;[]&gt;&gt;(
{([(&lt;{}[&lt;&gt;[]}&gt;{[]{[(&lt;()&gt;
(((({&lt;&gt;}&lt;{&lt;{&lt;&gt;}{[]{[]{}
[[&lt;[([]))&lt;([[{}[[()]]]
[{[{({}]{}}([{[{{{}}([]
{&lt;[[]]&gt;}&lt;{[{[{[]{()[[[]
[&lt;(&lt;(&lt;(&lt;{}))&gt;&lt;([]([]()
&lt;{([([[(&lt;&gt;()){}]&gt;(&lt;&lt;{{
&lt;{([{{}}[&lt;[[[&lt;&gt;{}]]]&gt;[]]
</code></pre>
</div>

<p>
Goal: Read the code and find a wrongly paired paren.
</p>

<p>
First parenthesis tools:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">snippet: {{{paren-tools}}}</span>
<span style="color: #483d8b;">define</span> opening<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-&gt;char-set</span> <span style="color: #8b2252;">"([{&lt;"</span>
<span style="color: #483d8b;">define</span> paired
<span style="color: #0000ff;">  '</span>
<span style="color: #0000ff;">    #\(</span><span style="color: #a020f0;"> . </span><span style="color: #008b8b;">#\)</span>
<span style="color: #0000ff;">    #\[</span><span style="color: #a020f0;"> . </span><span style="color: #008b8b;">#\]</span>
<span style="color: #0000ff;">    #\{</span><span style="color: #a020f0;"> . </span><span style="color: #008b8b;">#\}</span>
<span style="color: #0000ff;">    #\&lt;</span><span style="color: #a020f0;"> . </span>#\&gt;

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">opening?</span> char
<span style="color: #0000ff;">  char-set-contains?</span> opening char
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">valid-char?</span> letter-stack char
  <span style="color: #483d8b;">or</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">opening?</span> char
<span style="color: #0000ff;">       equal?</span> char<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">car</span> letter-stack
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">process</span> letter-stack char
  <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">opening?</span> char
<span style="color: #0000ff;">    cons</span> (<span style="color: #0000ff;">assoc-ref</span> paired char) letter-stack
<span style="color: #0000ff;">    cdr</span> letter-stack
</code></pre>
</div>

<p>
Now give the correct error codes:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> pretty-print) pretty-print
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :26) cut

{{{map-over-lines}}}
<span style="color: #b22222;">;; </span><span style="color: #b22222;">opening paired opening? valid-char? process</span>
{{{paren-tools}}}

<span style="color: #483d8b;">define</span> input
<span style="color: #0000ff;">  map-over-lines</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;</span> (<span style="color: #0000ff;">x</span>) x <span style="color: #b22222;">;; </span><span style="color: #b22222;">unchanged line, identity</span>
<span style="color: #a020f0;">    . </span><span style="color: #8b2252;">"advent-of-wisp-code-2021-d10p1-example-input.dat"</span>

<span style="color: #483d8b;">define</span> error-values
<span style="color: #0000ff;">  '</span>
<span style="color: #0000ff;">    #\)</span><span style="color: #a020f0;"> . </span><span style="color: #008b8b;">3</span>
<span style="color: #0000ff;">    #\]</span><span style="color: #a020f0;"> . </span><span style="color: #008b8b;">57</span>
<span style="color: #0000ff;">    #\}</span><span style="color: #a020f0;"> . </span><span style="color: #008b8b;">1197</span>
<span style="color: #0000ff;">    #\&gt;</span><span style="color: #a020f0;"> . </span><span style="color: #008b8b;">25137</span>

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">find-syntax-error</span> line
  <span style="color: #483d8b;">let</span> loop<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">(letter-stack</span> <span style="color: #008b8b;">'()</span>) (<span style="color: #0000ff;">open</span> (<span style="color: #0000ff;">string-&gt;list</span> line))
<span style="color: #0000ff;">    cond</span>
<span style="color: #a020f0;">      : </span><span style="color: #0000ff;">null?</span> open
<span style="color: #a020f0;">        . </span><span style="color: #008b8b;">#f</span>
<span style="color: #a020f0;">      : </span><span style="color: #0000ff;">valid-char?</span> letter-stack (<span style="color: #0000ff;">car</span> open)
<span style="color: #0000ff;">        loop</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">process</span> letter-stack (<span style="color: #0000ff;">car</span> open)
<span style="color: #0000ff;">               cdr</span> open
<span style="color: #0000ff;">      else</span>
<span style="color: #0000ff;">        car</span> open

<span style="color: #0000ff;">pretty-print</span>
<span style="color: #0000ff;">  apply</span> + 
<span style="color: #0000ff;">    map</span> (<span style="color: #0000ff;">cut</span> assoc-ref error-values &lt;&gt;)
<span style="color: #0000ff;">      delete</span> <span style="color: #008b8b;">#f</span>
<span style="color: #0000ff;">        map</span> find-syntax-error input
</code></pre>
</div>
]]></description>
</item>
<item>
<title>Day 10, Puzzle 2: Cleanly close closables</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-10-puzzle-2</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-10-puzzle-2</guid>
<pubDate>Tue, 28 Dec 2021 00:00:00 +0100</pubDate>

<description><![CDATA[<p>
Close unclosed parentheses, keep score of the kind of paren closed,
multiplying the previous by 5 for each new error.
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> pretty-print) pretty-print
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :26) cut
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :1) fold

{{{map-over-lines}}}
<span style="color: #b22222;">;; </span><span style="color: #b22222;">opening paired opening? valid-char? process</span>
{{{paren-tools}}}

<span style="color: #483d8b;">define</span> input
<span style="color: #0000ff;">  map-over-lines</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;</span> (<span style="color: #0000ff;">x</span>) x <span style="color: #b22222;">;; </span><span style="color: #b22222;">unchanged line, identity</span>
<span style="color: #a020f0;">    . </span><span style="color: #8b2252;">"advent-of-wisp-code-2021-d10p1-example-input.dat"</span>

<span style="color: #483d8b;">define</span> closing-values
<span style="color: #0000ff;">  '</span>
<span style="color: #0000ff;">    #\)</span><span style="color: #a020f0;"> . </span><span style="color: #008b8b;">1</span>
<span style="color: #0000ff;">    #\]</span><span style="color: #a020f0;"> . </span><span style="color: #008b8b;">2</span>
<span style="color: #0000ff;">    #\}</span><span style="color: #a020f0;"> . </span><span style="color: #008b8b;">3</span>
<span style="color: #0000ff;">    #\&gt;</span><span style="color: #a020f0;"> . </span><span style="color: #008b8b;">4</span>

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">score</span> numbers
  <span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">add-number</span> number prev
<span style="color: #0000ff;">    +</span> number<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">*</span> <span style="color: #008b8b;">5</span> prev
<span style="color: #0000ff;">  fold</span> add-number <span style="color: #008b8b;">0</span> numbers

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">find-syntax-error</span> line
  <span style="color: #483d8b;">let</span> loop<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">(letter-stack</span> <span style="color: #008b8b;">'()</span>) (<span style="color: #0000ff;">open</span> (<span style="color: #0000ff;">string-&gt;list</span> line))
<span style="color: #0000ff;">    cond</span>
<span style="color: #a020f0;">      : </span><span style="color: #0000ff;">null?</span> open
<span style="color: #0000ff;">        score</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> (<span style="color: #0000ff;">cut</span> assoc-ref closing-values &lt;&gt;) letter-stack
<span style="color: #a020f0;">      : </span><span style="color: #0000ff;">valid-char?</span> letter-stack (<span style="color: #0000ff;">car</span> open)
<span style="color: #0000ff;">        loop</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">process</span> letter-stack (<span style="color: #0000ff;">car</span> open)
<span style="color: #0000ff;">               cdr</span> open
<span style="color: #0000ff;">      else</span> <span style="color: #008b8b;">#f</span>

<span style="color: #0000ff;">pretty-print</span>
  <span style="color: #483d8b;">let</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> res<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">delete</span> <span style="color: #008b8b;">#f</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> find-syntax-error input
<span style="color: #0000ff;">    list-ref</span> (<span style="color: #0000ff;">sort</span> res &lt;)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">floor/</span> (<span style="color: #0000ff;">length</span> res) <span style="color: #008b8b;">2</span>
</code></pre>
</div>
]]></description>
</item>
<item>
<title>Day 11, Puzzle 1: Flashing Octopuses</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-11-puzzle-1</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-11-puzzle-1</guid>
<pubDate>Tue, 28 Dec 2021 00:00:00 +0100</pubDate>

<description><![CDATA[<p>
Every step each number is increased by 1. If it is higher than 9, it
flashes, and the up to 8 sourrounding numbers increase by 1, too, also
flashing if they become higher than 9.
</p>

<div class="org-src-container">
<pre class="src src-scheme"><code>5483143223
2745854711
5264556173
6141336146
6357385478
4167524645
2176841721
6882881134
4846848554
5283751526
</code></pre>
</div>

<p>
Flashing logic:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">snippet: {{{flashing-logic}}}</span>
<span style="color: #483d8b;">define</span> input
<span style="color: #0000ff;">  map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;</span> (<span style="color: #0000ff;">x</span>) (<span style="color: #0000ff;">map</span> string-&gt;number (<span style="color: #0000ff;">map</span> string x))
<span style="color: #0000ff;">    map-over-lines</span> string-&gt;list <span style="color: #8b2252;">"advent-of-wisp-code-2021-d11p1-example-input.dat"</span>

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">1++</span> arr
<span style="color: #a020f0;">  . </span><span style="color: #8b2252;">"increase every arr value by 1"</span>
<span style="color: #0000ff;">  map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;</span> (<span style="color: #0000ff;">x</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> 1+ x
<span style="color: #a020f0;">      . </span>arr

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">flash-indizes</span> arr
  <span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">flash</span> y
    <span style="color: #483d8b;">define</span> L<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">list-ref</span> arr y
<span style="color: #0000ff;">    map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cut</span> cons y &lt;&gt;
<span style="color: #0000ff;">      delete</span> <span style="color: #008b8b;">#f</span>
<span style="color: #0000ff;">        map</span>
<span style="color: #0000ff;">          &#955;(idx)</span>
              <span style="color: #483d8b;">let</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> num<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">list-ref</span> L idx
                  <span style="color: #b22222;">;; </span><span style="color: #b22222;">99 means "already flashing"</span>
                  <span style="color: #483d8b;">and</span> {num &gt; 9} {num &lt; 99} idx
<span style="color: #0000ff;">          iota</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">length</span> L
<span style="color: #0000ff;">  apply</span> append<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> flash<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">iota</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">length</span> arr


<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">flash</span> arr
<span style="color: #a020f0;">  . </span><span style="color: #8b2252;">"return as values: changed arr and count of flashing"</span>
  <span style="color: #483d8b;">let</span> reflash<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> count <span style="color: #008b8b;">0</span>
    <span style="color: #483d8b;">define</span> indizes<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">flash-indizes</span> arr
    <span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply-flash</span> index
      <span style="color: #483d8b;">define</span> y<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">car</span> index
      <span style="color: #483d8b;">define</span> x<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cdr</span> index
      <span style="color: #483d8b;">define</span> line<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">list-ref</span> arr y
      <span style="color: #483d8b;">define</span> len-line-1<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">1-</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">length</span> line
      <span style="color: #483d8b;">define</span> len-arr-1<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">1-</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">length</span> arr
      <span style="color: #b22222;">;; </span><span style="color: #b22222;">all indizes around the current index</span>
      <span style="color: #b22222;">;; </span><span style="color: #b22222;">but only inside the limits</span>
      <span style="color: #483d8b;">define</span> around
<span style="color: #0000ff;">        delete</span> <span style="color: #008b8b;">#f</span>
<span style="color: #0000ff;">          list</span> <span style="color: #b22222;">;; </span><span style="color: #b22222;">#f if outside the limits</span>
             <span style="color: #483d8b;">and</span> {x &gt; 0}
<span style="color: #0000ff;">                 cons</span> {x - 1} y
             <span style="color: #483d8b;">and</span> {x &lt; len-line-1}
<span style="color: #0000ff;">                 cons</span> {x + 1} y
             <span style="color: #483d8b;">and</span> {y &lt; len-arr-1}
<span style="color: #0000ff;">                 cons</span> x {y + 1}
             <span style="color: #483d8b;">and</span> (<span style="color: #483d8b;">and</span> {y &lt; len-arr-1} {x &gt; 0})
<span style="color: #0000ff;">                 cons</span> {x - 1} {y + 1}
             <span style="color: #483d8b;">and</span> (<span style="color: #483d8b;">and</span> {y &lt; len-arr-1} {x &lt; len-line-1})
<span style="color: #0000ff;">                 cons</span> {x + 1} {y + 1}
             <span style="color: #483d8b;">and</span> {y &gt; 0}
<span style="color: #0000ff;">                 cons</span> x {y - 1}
             <span style="color: #483d8b;">and</span> (<span style="color: #483d8b;">and</span> {y &gt; 0} {x &gt; 0})
<span style="color: #0000ff;">                 cons</span> {x - 1} {y - 1}
             <span style="color: #483d8b;">and</span> (<span style="color: #483d8b;">and</span> {y &gt; 0} {x &lt; len-line-1})
<span style="color: #0000ff;">                 cons</span> {x + 1} {y - 1}
<span style="color: #0000ff;">      for-each</span>
<span style="color: #0000ff;">        &#955;</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">x</span> y
          <span style="color: #483d8b;">let</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> line<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">list-ref</span> arr y
<span style="color: #0000ff;">            list-set!</span> line x<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">1+</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">list-ref</span> line x
<span style="color: #0000ff;">            list-set!</span> arr y line
<span style="color: #0000ff;">        map</span> car around
<span style="color: #0000ff;">        map</span> cdr around
      <span style="color: #b22222;">;; </span><span style="color: #b22222;">99 means "already flashing"</span>
<span style="color: #0000ff;">      list-set!</span> line x <span style="color: #008b8b;">99</span>
    <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">null?</span> indizes
       <span style="color: #b22222;">;; </span><span style="color: #b22222;">use multiple values return as a side-channel </span>
       <span style="color: #b22222;">;; </span><span style="color: #b22222;">to report the number of flashes (as count)</span>
<span style="color: #0000ff;">       values</span>
<span style="color: #0000ff;">         map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;</span> (<span style="color: #0000ff;">line</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> (<span style="color: #0000ff;">&#955;</span> (<span style="color: #0000ff;">num</span>) (<span style="color: #483d8b;">if</span> {num &gt;= 99} <span style="color: #008b8b;">0</span> num)) line
<span style="color: #a020f0;">             . </span>arr
<span style="color: #a020f0;">         . </span>count
<span style="color: #0000ff;">       begin</span>
<span style="color: #0000ff;">         for-each</span> apply-flash indizes
<span style="color: #0000ff;">         reflash</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">+</span> count<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">length</span> indizes

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">step</span> arr
<span style="color: #0000ff;">  flash</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">1++</span> arr
</code></pre>
</div>

<p>
Put it together:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> pretty-print) pretty-print
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :26) cut
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :1) fold first second
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :11) let-values

{{{map-over-lines}}}
<span style="color: #b22222;">;; </span><span style="color: #b22222;">input, step</span>
{{{flashing-logic}}}

<span style="color: #483d8b;">define</span> flash-counter <span style="color: #008b8b;">0</span>

<span style="color: #0000ff;">display</span>
<span style="color: #0000ff;">  string-join</span>
<span style="color: #0000ff;">    map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;</span> (<span style="color: #0000ff;">line</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-join</span> (<span style="color: #0000ff;">map</span> number-&gt;string line) <span style="color: #8b2252;">""</span>
<span style="color: #0000ff;">      fold</span> 
<span style="color: #0000ff;">         &#955;</span> (<span style="color: #0000ff;">num</span> prev)
<span style="color: #0000ff;">           let-values</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> (<span style="color: #0000ff;">arr</span> count) (<span style="color: #0000ff;">step</span> prev)
             <span style="color: #483d8b;">set!</span> flash-counter {flash-counter + count}
<span style="color: #a020f0;">             . </span>arr
<span style="color: #a020f0;">         . </span>input
<span style="color: #0000ff;">         iota</span> <span style="color: #008b8b;">100</span>
<span style="color: #a020f0;">    . </span><span style="color: #8b2252;">"\n"</span>
<span style="color: #0000ff;">newline</span>
<span style="color: #0000ff;">display</span> flash-counter
</code></pre>
</div>
]]></description>
</item>
<item>
<title>Day 11, Puzzle 2: Flash together, right now</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-11-puzzle-2</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-11-puzzle-2</guid>
<pubDate>Wed, 26 Jan 2022 22:47:00 +0100</pubDate>

<description><![CDATA[<p>
Find the step where all flashh together.
</p>

<p>
Use a local return to stop the fold when I find the flashing.
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> pretty-print) pretty-print
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> control) call/ec <span style="color: #b22222;">; </span><span style="color: #b22222;">non-local exit -&gt; return</span>
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :26) cut
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :1) fold first second
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :11) let-values

{{{map-over-lines}}}
<span style="color: #b22222;">;; </span><span style="color: #b22222;">input, step</span>
<span style="color: #0000ff;">{{{flashing-logic}}}</span>

<span style="color: #0000ff;">display</span>
<span style="color: #0000ff;">  string-join</span>
<span style="color: #0000ff;">    map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;</span> (<span style="color: #0000ff;">line</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-join</span> (<span style="color: #0000ff;">map</span> number-&gt;string line) <span style="color: #8b2252;">""</span>
      <span style="color: #b22222;">;; </span><span style="color: #b22222;">introduce a return statement locally</span>
<span style="color: #0000ff;">      call/ec</span>
<span style="color: #0000ff;">        &#955;</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">return</span>
<span style="color: #0000ff;">          fold</span>
<span style="color: #0000ff;">             &#955;</span> (<span style="color: #0000ff;">num</span> prev)
<span style="color: #0000ff;">               let-values</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> (<span style="color: #0000ff;">arr</span> count) (<span style="color: #0000ff;">step</span> prev)
                 <span style="color: #483d8b;">when</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">=</span> <span style="color: #008b8b;">0</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> +<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> (<span style="color: #0000ff;">&#955;(x</span>) (<span style="color: #0000ff;">apply</span> + x)) arr
<span style="color: #0000ff;">                   return</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">append</span> arr `(<span style="color: #0000ff;">(,(+</span> <span style="color: #008b8b;">1</span> num)))
<span style="color: #a020f0;">                 . </span>arr
<span style="color: #a020f0;">             . </span>input
<span style="color: #0000ff;">             iota</span> <span style="color: #008b8b;">1999</span>
<span style="color: #a020f0;">    . </span><span style="color: #8b2252;">"\n"</span>

</code></pre>
</div>
]]></description>
</item>
<item>
<title>Day 12, Puzzle 1: All the exciting trails</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-12-puzzle-1</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-12-puzzle-1</guid>
<pubDate>Sat, 14 May 2022 07:04:00 +0200</pubDate>

<description><![CDATA[<p>
Find all paths through the cave that visit small caves only once.
</p>

<p>
I enter at <code>start</code>, I exit at <code>end</code>, I’m only allowed to enter
uppercase rooms more than once. These are the edges (the connections)
between rooms that give 10 paths:
</p>


<div class="org-src-container">
<pre class="src src-scheme"><code>start-A
start-b
A-c
A-b
b-d
A-end
b-end
</code></pre>
</div>

<p>
And a larger input with 226 paths:
</p>

<div class="org-src-container">
<pre class="src src-scheme"><code>fs-end
he-DX
fs-he
start-DX
pj-DX
end-zg
zg-sl
zg-pj
pj-he
RW-he
fs-DX
pj-RW
zg-RW
start-pj
he-WI
zg-he
pj-fs
start-RW
</code></pre>
</div>


<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> pretty-print) pretty-print
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :26) cut
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :1) first second append-map remove

{{{map-over-lines}}}

<span style="color: #483d8b;">define</span> input
<span style="color: #0000ff;">  map-over-lines</span>
<span style="color: #0000ff;">    cut</span> string-split &lt;&gt; <span style="color: #008b8b;">#\-</span>
<span style="color: #a020f0;">    . </span><span style="color: #8b2252;">"advent-of-wisp-code-2021-d12p1-example-input-larger.dat"</span>

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">undirected</span> edges
<span style="color: #0000ff;">  append-map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;</span> (<span style="color: #0000ff;">edge</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">list</span> edge (<span style="color: #0000ff;">reverse</span> edge)
<span style="color: #a020f0;">    . </span>edges

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">all-paths</span> edges
  <span style="color: #483d8b;">let</span> loop<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">(path</span> '(<span style="color: #8b2252;">"start"</span>)) (<span style="color: #0000ff;">edges</span> (<span style="color: #0000ff;">undirected</span> edges))
    <span style="color: #483d8b;">define</span> matching-edges
      <span style="color: #b22222;">;; </span><span style="color: #b22222;">keep the edges that match the first element of the path</span>
<span style="color: #0000ff;">      filter</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;</span> (<span style="color: #0000ff;">edge</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">equal?</span> (<span style="color: #0000ff;">first</span> edge) (<span style="color: #0000ff;">first</span> path)
<span style="color: #a020f0;">        . </span>edges
    <span style="color: #483d8b;">define</span> remaining-edges
      <span style="color: #b22222;">;; </span><span style="color: #b22222;">remove edges that match the first element of the path</span>
      <span style="color: #b22222;">;; </span><span style="color: #b22222;">if we&#8217;re in a lowercase field, otherwise keep all</span>
      <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-every</span> char-set:upper-case (<span style="color: #0000ff;">first</span> path)
<span style="color: #a020f0;">         . </span>edges
<span style="color: #0000ff;">         remove</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;</span> (<span style="color: #0000ff;">edge</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">equal?</span> (<span style="color: #0000ff;">first</span> edge) (<span style="color: #0000ff;">first</span> path)
<span style="color: #a020f0;">           . </span>edges
    <span style="color: #483d8b;">define</span> extended-paths-for-matching
      <span style="color: #b22222;">;; </span><span style="color: #b22222;">create one extended path for each matching edge</span>
<span style="color: #0000ff;">      map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;</span> (<span style="color: #0000ff;">edge</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cons</span> (<span style="color: #0000ff;">second</span> edge) path
<span style="color: #a020f0;">          . </span>matching-edges
    <span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">process-one</span> extended-path
<span style="color: #0000ff;">      loop</span> extended-path  remaining-edges
<span style="color: #0000ff;">    cond</span>
<span style="color: #a020f0;">      : </span><span style="color: #0000ff;">equal?</span> <span style="color: #8b2252;">"end"</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">first</span> path
<span style="color: #0000ff;">        list</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-join</span> (<span style="color: #0000ff;">reverse</span> path) <span style="color: #8b2252;">","</span>
<span style="color: #a020f0;">      : </span><span style="color: #0000ff;">null?</span> edges
<span style="color: #0000ff;">        list</span> <span style="color: #b22222;">;; </span><span style="color: #b22222;">empty, because we did not reach the end</span>
<span style="color: #0000ff;">      else</span>
<span style="color: #0000ff;">        append-map</span> process-one extended-paths-for-matching

<span style="color: #0000ff;">pretty-print</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">length</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">all-paths</span> input
</code></pre>
</div>
]]></description>
</item>
<item>
<title>Day 12, Puzzle 2: Accept boredom just once</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-12-puzzle-2</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-12-puzzle-2</guid>
<pubDate>Sat, 14 May 2022 07:04:00 +0200</pubDate>

<description><![CDATA[<p>
Find all paths through the cave that visit small caves only once;
except that you may visit one of them twice.
</p>

<p>
I enter at <code>start</code>, I exit at <code>end</code>, I’m allowed to enter
uppercase rooms more than once. These are the edges (the connections)
between rooms that give 36 paths:
</p>


<div class="org-src-container">
<pre class="src src-scheme"><code>start-A
start-b
A-c
A-b
b-d
A-end
b-end
</code></pre>
</div>

<p>
And a larger input with 3509 paths:
</p>

<div class="org-src-container">
<pre class="src src-scheme"><code>fs-end
he-DX
fs-he
start-DX
pj-DX
end-zg
zg-sl
zg-pj
pj-he
RW-he
fs-DX
pj-RW
zg-RW
start-pj
he-WI
zg-he
pj-fs
start-RW
</code></pre>
</div>

<p>
This looks harmless, but it originally pushed my non-optimized code to its limits
and got my CPU to suffer. It could benefit a lot from a functional
dictionary datastructure instead of a linear-update alist. But still, it’s
nice to my memory and already did the job.
</p>

<p>
After finishing it, I optimized it to avoid doing work twice, so this now has reasonable speed.
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> pretty-print) pretty-print
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :26) cut
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :1) first second append-map remove

{{{map-over-lines}}}

<span style="color: #483d8b;">define</span> input
<span style="color: #0000ff;">  map-over-lines</span>
<span style="color: #0000ff;">    cut</span> string-split &lt;&gt; <span style="color: #008b8b;">#\-</span>
<span style="color: #a020f0;">    . </span><span style="color: #8b2252;">"advent-of-wisp-code-2021-d12p1-example-input.dat"</span>

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">undirected</span> edges
<span style="color: #0000ff;">  append-map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;</span> (<span style="color: #0000ff;">edge</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">list</span> edge (<span style="color: #0000ff;">reverse</span> edge)
<span style="color: #a020f0;">    . </span>edges

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">lower?</span> str
<span style="color: #0000ff;">  string-every</span> char-set:lower-case str

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">all-paths</span> edges
  <span style="color: #483d8b;">let</span> loop<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">(path</span> '(<span style="color: #8b2252;">"start"</span>)) (<span style="color: #0000ff;">edges</span> (<span style="color: #0000ff;">undirected</span> edges)) (<span style="color: #0000ff;">bored?</span> <span style="color: #008b8b;">#f</span>)
    <span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">twice-in-path?</span>
      <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">member</span> (<span style="color: #0000ff;">first</span> path) (<span style="color: #0000ff;">cdr</span> path)
<span style="color: #a020f0;">         . </span><span style="color: #008b8b;">#t</span> <span style="color: #008b8b;">#f</span>
    <span style="color: #483d8b;">define</span> path-head<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">first</span> path
    <span style="color: #483d8b;">define</span> start?<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">equal?</span> path-head <span style="color: #8b2252;">"start"</span>
    <span style="color: #483d8b;">define</span> end?<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">equal?</span> path-head <span style="color: #8b2252;">"end"</span>
    <span style="color: #483d8b;">define</span> lowercase?<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">lower?</span> path-head
    <span style="color: #483d8b;">define</span> boring?<span style="color: #a020f0;"> : </span><span style="color: #483d8b;">and</span> lowercase?<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">twice-in-path?</span>
    <span style="color: #483d8b;">define</span> matching-edges
      <span style="color: #b22222;">;; </span><span style="color: #b22222;">keep the edges that match the first element of the path</span>
<span style="color: #0000ff;">      filter</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;</span> (<span style="color: #0000ff;">edge</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">equal?</span> path-head<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">first</span> edge
<span style="color: #a020f0;">        . </span>edges
    <span style="color: #483d8b;">define</span> remaining-edges
      <span style="color: #b22222;">;; </span><span style="color: #b22222;">remove edges that match the first element of the path </span>
      <span style="color: #b22222;">;; </span><span style="color: #b22222;">if we&#8217;re in a lowercase field, otherwise keep all</span>
<span style="color: #0000ff;">      cond</span>
<span style="color: #0000ff;">        boring?</span> <span style="color: #b22222;">;; </span><span style="color: #b22222;">remove the current edge and all lowercase path elements</span>
          <span style="color: #483d8b;">let</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> lowercase-path-elements<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">filter</span> lower? path
<span style="color: #0000ff;">            remove</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;</span> (<span style="color: #0000ff;">edge</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">member</span> (<span style="color: #0000ff;">first</span> edge) lowercase-path-elements
<span style="color: #a020f0;">              . </span>edges
<span style="color: #a020f0;">        : </span><span style="color: #483d8b;">or</span>  start?<span style="color: #a020f0;"> : </span><span style="color: #483d8b;">and</span> bored? lowercase?
<span style="color: #0000ff;">          remove</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;</span> (<span style="color: #0000ff;">edge</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">equal?</span> path-head<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">first</span> edge
<span style="color: #a020f0;">           . </span>edges
<span style="color: #0000ff;">        else</span> edges <span style="color: #b22222;">;; </span><span style="color: #b22222;">keep all</span>
    <span style="color: #483d8b;">define</span> extended-paths-for-matching
      <span style="color: #b22222;">;; </span><span style="color: #b22222;">create one extended path for each matching edge</span>
<span style="color: #0000ff;">      map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;</span> (<span style="color: #0000ff;">edge</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cons</span> (<span style="color: #0000ff;">second</span> edge) path
<span style="color: #a020f0;">          . </span>matching-edges
    <span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">process-one</span> extended-path
<span style="color: #0000ff;">      loop</span> extended-path  remaining-edges<span style="color: #a020f0;"> : </span><span style="color: #483d8b;">or</span> bored? boring?
<span style="color: #0000ff;">    cond</span>
<span style="color: #0000ff;">      end?</span>
<span style="color: #0000ff;">        list</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-join</span> (<span style="color: #0000ff;">reverse</span> path) <span style="color: #8b2252;">","</span>
<span style="color: #a020f0;">      : </span><span style="color: #0000ff;">null?</span> edges
<span style="color: #0000ff;">        list</span> <span style="color: #b22222;">;; </span><span style="color: #b22222;">empty, because we did not reach the end</span>
<span style="color: #a020f0;">      : </span><span style="color: #483d8b;">and</span> start?<span style="color: #a020f0;"> : </span><span style="color: #483d8b;">not</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">null?</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cdr</span> path
<span style="color: #0000ff;">        list</span> <span style="color: #b22222;">;; </span><span style="color: #b22222;">empty, because revisiting start is forbidden</span>
<span style="color: #0000ff;">      else</span>
<span style="color: #0000ff;">        append-map</span> process-one extended-paths-for-matching

<span style="color: #0000ff;">pretty-print</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">length</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">all-paths</span> input
</code></pre>
</div>

<p>
Profiling this, gives the expected results: <code>remove</code>, <code>string-every</code>
and <code>lower?</code> are the most expensive actions, since they are the inner
loops. To profile it, just copy it into a wisp shell and then run:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">,profile</span> pretty-print<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">length</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">all-paths</span> input .
</code></pre>
</div>

<p>
The output with profile looks like this:
</p>

<pre class="example" id="org0a4982e">
3509
%     cumulative   self             
time   seconds     seconds  procedure
 26.47      0.16      0.16  string-every-c-code
 14.71      0.16      0.09  remove
 14.71      0.11      0.09  lower?
 11.76      0.07      0.07  &lt;current input&gt;:50:39
  8.82      0.62      0.05  &lt;current input&gt;:31:38:loop
  8.82      0.07      0.05  &lt;current input&gt;:71:0
  2.94      0.38      0.02  filter
  2.94      0.02      0.02  car
  2.94      0.02      0.02  %after-gc-thunk
  2.94      0.02      0.02  string-join
  2.94      0.02      0.02  procedure?
  0.00     15.13      0.00  srfi/srfi-1.scm:584:5:map1
  0.00      5.55      0.00  srfi/srfi-1.scm:672:0:append-map
  0.00      0.62      0.00  anon #x1752678
  0.00      0.02      0.00  anon #xe3d160
  0.00      0.02      0.00  ice-9/boot-9.scm:340:2:string-every
---
Sample count: 34
Total time: 0.621091946 seconds (0.093273494 seconds in GC)
</pre>

<p>
Since string-every, remove and lower? already have 0.34s — more than
half the runtime — I won’t optimize further. A better datastructure
could get rid of most of the cost of remove, and the lower? could be
cached to save another 10% of the runtime, for example like this:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #483d8b;">define</span> lower?
  <span style="color: #483d8b;">let</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> cache <span style="color: #008b8b;">'()</span>
<span style="color: #0000ff;">    lambda</span> (<span style="color: #0000ff;">str</span>)
      <span style="color: #483d8b;">let</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> cached<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">assoc</span> str cache
        <span style="color: #483d8b;">if</span> cached
<span style="color: #0000ff;">          cdr</span> cached
          <span style="color: #483d8b;">let</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> res<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-every</span> char-set:lower-case str
            <span style="color: #483d8b;">set!</span> cache<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cons</span> (<span style="color: #0000ff;">cons</span> str res) cache
<span style="color: #a020f0;">            . </span>res
</code></pre>
</div>

<p>
See, now I did optimize further, but I’ll stop here :-)
</p>

<p>
Have fun!
</p>
]]></description>
</item>
<item>
<title>Day 13, Puzzle 1: Fold your password</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-13-puzzle-1</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-13-puzzle-1</guid>
<pubDate>Sat, 08 Oct 2022 09:50:00 +0200</pubDate>

<description><![CDATA[<p>
Mirror points over a given axis.
</p>



<div class="org-src-container">
<pre class="src src-scheme"><code>6,10
0,14
9,10
0,3
10,4
4,11
6,0
6,12
4,1
0,13
10,12
3,4
3,0
8,4
1,10
2,14
8,10
9,0

fold along y=7
fold along x=5
</code></pre>
</div>

<p>
Here I need to read two fields. I realize that with a modification of <code>map-over-lines</code>:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">snippet: {{{map-over-lines-port}}}: an alternate map-over-lines</span>
<span style="color: #b22222;">;; </span><span style="color: #b22222;">that takes a port and a terminator, so multiple fields can be read</span>
<span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :26) cut
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> optargs) define*
<span style="color: #0000ff;">define*</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map-over-lines/port</span> fun port #:key (<span style="color: #0000ff;">terminator</span> eof-object?)
  <span style="color: #483d8b;">define</span> terminator?
    <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #483d8b;">or</span>  (<span style="color: #0000ff;">procedure?</span> terminator) (<span style="color: #0000ff;">macro?</span> terminator)
<span style="color: #a020f0;">       . </span>terminator
<span style="color: #0000ff;">       cut</span> equal? terminator &lt;&gt;
  <span style="color: #483d8b;">let</span> loop<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">(lines</span> <span style="color: #008b8b;">'()</span>) (<span style="color: #0000ff;">line</span> (<span style="color: #0000ff;">read-line</span> port))
    <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">terminator?</span> line
<span style="color: #0000ff;">      begin</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">reverse!</span> lines
<span style="color: #0000ff;">      loop</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cons</span> (<span style="color: #0000ff;">fun</span> line) lines
<span style="color: #0000ff;">             read-line</span> port
</code></pre>
</div>

<p>
Also I need to draw coordinates on the commandline:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">snippet: {{{draw-coordinates}}}</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">draw</span> coordinates
  <span style="color: #483d8b;">define</span> xs<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> first coordinates
  <span style="color: #483d8b;">define</span> ys<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> second coordinates
  <span style="color: #483d8b;">define</span> len-x
<span style="color: #0000ff;">    +</span> <span style="color: #008b8b;">1</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> max xs
  <span style="color: #483d8b;">define</span> len-y
<span style="color: #0000ff;">    +</span> <span style="color: #008b8b;">1</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> max ys
  <span style="color: #483d8b;">define</span> pane
    <span style="color: #483d8b;">let</span> loop<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">(res</span> <span style="color: #008b8b;">'()</span>) (<span style="color: #0000ff;">rest-y</span> len-y)
      <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">zero?</span> rest-y
<span style="color: #a020f0;">         . </span>res
<span style="color: #0000ff;">         loop</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cons</span> (<span style="color: #0000ff;">make-list</span> len-x <span style="color: #008b8b;">#\.)</span> res
<span style="color: #0000ff;">                -</span> rest-y <span style="color: #008b8b;">1</span>
<span style="color: #0000ff;">  for-each</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;</span> (<span style="color: #0000ff;">x</span> y)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">list-set!</span> (<span style="color: #0000ff;">list-ref</span> pane y) x <span style="color: #008b8b;">#\#</span>
<span style="color: #a020f0;">             . </span>xs ys
<span style="color: #0000ff;">  string-join</span>
<span style="color: #0000ff;">    map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;</span> (<span style="color: #0000ff;">sublist</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> string sublist
<span style="color: #a020f0;">       . </span>pane
<span style="color: #a020f0;">    . </span><span style="color: #8b2252;">"\n"</span>
</code></pre>
</div>

<p>
And I need to read the coordinates <i>and</i> instructions and apply instructions:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">snippet: {{{coordinates-and-instructions}}}</span>
<span style="color: #0000ff;">define-values</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">coordinates</span> instructions
  <span style="color: #483d8b;">let</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> port<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">open-input-file</span> <span style="color: #8b2252;">"advent-of-wisp-code-2021-d13p1-example-input.dat"</span>
    <span style="color: #483d8b;">define</span> coordinates
<span style="color: #0000ff;">        map-over-lines/port</span>
<span style="color: #0000ff;">          &#955;</span> (<span style="color: #0000ff;">line</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> string-&gt;number<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-split</span> line <span style="color: #008b8b;">#\,</span>
<span style="color: #a020f0;">          . </span>port
<span style="color: #a020f0;">          . </span>#:terminator <span style="color: #8b2252;">""</span> <span style="color: #b22222;">;; </span><span style="color: #b22222;">split by empty line</span>
    <span style="color: #483d8b;">define</span> instructions
<span style="color: #0000ff;">      map-over-lines/port</span>
<span style="color: #0000ff;">        cut</span> string-split &lt;&gt; <span style="color: #008b8b;">#\=</span>
<span style="color: #a020f0;">        . </span>port
<span style="color: #0000ff;">    values</span> coordinates instructions

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply-instruction</span> coordinates instruction
  <span style="color: #483d8b;">define</span> instruction-value<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-&gt;number</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">second</span> instruction
  <span style="color: #483d8b;">define</span> is-y<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">equal?</span> <span style="color: #8b2252;">"fold along y"</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">first</span> instruction
  <span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">process-one</span> coordinate
    <span style="color: #483d8b;">define</span> val<span style="color: #a020f0;"> : </span><span style="color: #483d8b;">if</span> is-y (<span style="color: #0000ff;">second</span> coordinate) (<span style="color: #0000ff;">first</span> coordinate)
    <span style="color: #483d8b;">define</span> new-val
      <span style="color: #483d8b;">if</span> {val &lt; instruction-value} val
<span style="color: #0000ff;">         -</span> {instruction-value * 2} val
    <span style="color: #483d8b;">if</span> is-y
<span style="color: #0000ff;">      list</span> (<span style="color: #0000ff;">first</span> coordinate) new-val
<span style="color: #0000ff;">      list</span> new-val (<span style="color: #0000ff;">second</span> coordinate)
<span style="color: #0000ff;">  map</span> process-one coordinates
</code></pre>
</div>

<p>
Finally: actually apply one instruction, and draw the coordinates:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> pretty-print) pretty-print
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> optargs) define*
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :26) cut
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :1) first second append-map remove

<span style="color: #0000ff;">{{{map-over-lines-port}}}</span>
<span style="color: #0000ff;">{{{draw-coordinates}}}</span>
<span style="color: #0000ff;">{{{coordinates-and-instructions}}}</span>

<span style="color: #0000ff;">display</span>
<span style="color: #0000ff;">  string-count</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">draw</span> <span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply-instruction</span> coordinates<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">car</span> instructions
<span style="color: #a020f0;">    . </span><span style="color: #008b8b;">#\#</span>

</code></pre>
</div>

<p>
I did too much when solving this: I directly implemented folding to the
end, because I did not read the final paragraph carefully enough.
</p>

<p>
I took that additional part out again for the code above. It’s in the
code for part 2.
</p>
]]></description>
</item>
<item>
<title>Day 13, Puzzle 2: Fold your password</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-13-puzzle-2</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-13-puzzle-2</guid>
<pubDate>Sun, 16 Oct 2022 10:18:00 +0200</pubDate>

<description><![CDATA[<p>
Complete folding, then use the letters as result (in the example: O).
The only changees are creating folded by let-recursion over the
instructions and printing the drawing instead of the count.
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> pretty-print) pretty-print
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> optargs) define*
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :26) cut
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :1) first second append-map remove

{{{map-over-lines-port}}}
{{{draw-coordinates}}}
{{{coordinates-and-instructions}}}

<span style="color: #483d8b;">define</span> folded
  <span style="color: #483d8b;">let</span> loop<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">(coords</span> coordinates) (<span style="color: #0000ff;">instrs</span> instructions)
    <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">null?</span> instrs
<span style="color: #a020f0;">       . </span>coords
<span style="color: #0000ff;">       loop</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply-instruction</span> coords<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">car</span> instrs
<span style="color: #0000ff;">              cdr</span> instrs

<span style="color: #0000ff;">display</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">draw</span> folded

</code></pre>
</div>

<p>
And since it just calls for it, let’s follow Scheme tradition and
implement <code>map-over-lines</code> on top of <code>map-over-lines/port</code>:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code>{{{map-over-lines-port}}}
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map-over-lines</span> fun filename
  <span style="color: #483d8b;">define</span> port<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">open-input-file</span> filename
  <span style="color: #483d8b;">define</span> lines<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map-over-lines/port</span> fun port
<span style="color: #0000ff;">  close</span> port
<span style="color: #a020f0;">  . </span>lines
</code></pre>
</div>

<p>
This closes the port explicitly. Without that, closing is delayed
until garbage-collection which could exhaust file descriptors if I
open many files in a very short time.
</p>
]]></description>
</item>
<item>
<title>Day 14, Puzzle 1: Polymer-synthesis</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-14-puzzle-1</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-14-puzzle-1</guid>
<pubDate>Fri, 11 Nov 2022 08:00:00 +0100</pubDate>

<description><![CDATA[<p>
Insert characters inside matching pairs.
</p>

<p>
The first line is the initial sequence. A second block gives a lookup table: insert the character in the middle of matching pairs.
</p>

<div class="org-src-container">
<pre class="src src-scheme"><code>NNCB

CH -&gt; B
HH -&gt; N
CB -&gt; H
NH -&gt; C
HB -&gt; C
HC -&gt; B
HN -&gt; C
NN -&gt; C
BH -&gt; H
NC -&gt; B
NB -&gt; B
BN -&gt; B
BB -&gt; N
BC -&gt; B
CC -&gt; N
CN -&gt; C
</code></pre>
</div>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">srfi</span> :1) take first second fold
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> string-fun) string-replace-substring
{{{map-over-lines-port}}}

<span style="color: #483d8b;">define</span> input
  <span style="color: #483d8b;">let</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> port<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">open-input-file</span> <span style="color: #8b2252;">"advent-of-wisp-code-2021-d14p1-example-input.dat"</span>
    <span style="color: #483d8b;">define</span> init
<span style="color: #0000ff;">        first</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map-over-lines/port</span> string-&gt;list port #:terminator <span style="color: #8b2252;">""</span>
    <span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">split-line</span> line
        <span style="color: #483d8b;">define</span> key-value
<span style="color: #0000ff;">          string-split</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-replace-substring</span> line <span style="color: #8b2252;">" -&gt; "</span> <span style="color: #8b2252;">";"</span>
<span style="color: #a020f0;">            . </span><span style="color: #008b8b;">#\;</span>
<span style="color: #0000ff;">        cons</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-&gt;list</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">first</span> key-value
<span style="color: #0000ff;">               first</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-&gt;list</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">second</span> key-value
    <span style="color: #483d8b;">define</span> rules
<span style="color: #0000ff;">        map-over-lines/port</span> split-line port
<span style="color: #0000ff;">    list</span> init rules

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply-rule</span> left right prev rules
  <span style="color: #483d8b;">define</span> matching<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">assoc</span> (<span style="color: #0000ff;">list</span> left right) rules
  <span style="color: #483d8b;">define</span> prev-with-match
      <span style="color: #483d8b;">if</span> matching<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cons</span> (<span style="color: #0000ff;">cdr</span> matching) prev
<span style="color: #a020f0;">         . </span>prev
<span style="color: #0000ff;">  cons</span> right prev-with-match

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply-rules</span> letters rules
<span style="color: #0000ff;">  reverse!</span>
<span style="color: #0000ff;">    fold</span> (<span style="color: #0000ff;">cut</span> apply-rule &lt;&gt; &lt;&gt; &lt;&gt; rules)
<span style="color: #0000ff;">      take</span> letters <span style="color: #008b8b;">1</span> <span style="color: #b22222;">;; </span><span style="color: #b22222;">initial value: first letter</span>
<span style="color: #a020f0;">      . </span>letters <span style="color: #b22222;">;; </span><span style="color: #b22222;">left letters in pairs</span>
<span style="color: #0000ff;">      cdr</span> letters <span style="color: #b22222;">;; </span><span style="color: #b22222;">shifted =&gt; right right letters</span>

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply-rules-n-times</span> N letters rules
  <span style="color: #483d8b;">let</span> loop<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">(N</span> N) (<span style="color: #0000ff;">letters</span> letters)
    <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">zero?</span> N
<span style="color: #a020f0;">       . </span>letters
<span style="color: #0000ff;">       loop</span> {N - 1}
<span style="color: #0000ff;">         apply-rules</span> letters rules

<span style="color: #483d8b;">define</span> result-string
<span style="color: #0000ff;">  apply</span> string
<span style="color: #0000ff;">    apply-rules-n-times</span> <span style="color: #008b8b;">10</span> (<span style="color: #0000ff;">first</span> input) (<span style="color: #0000ff;">second</span> input)

<span style="color: #483d8b;">define</span> all-possible-letters
   <span style="color: #483d8b;">let</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> with-duplicates<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">append</span> (<span style="color: #0000ff;">first</span> input)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> cdr (<span style="color: #0000ff;">second</span> input)
     <span style="color: #b22222;">;; </span><span style="color: #b22222;">hack: use char-set conversion to remove duplicates</span>
<span style="color: #0000ff;">     char-set-&gt;list</span>
<span style="color: #0000ff;">       list-&gt;char-set</span> with-duplicates

<span style="color: #483d8b;">define</span> occurrences
<span style="color: #0000ff;">  map</span> (<span style="color: #0000ff;">cut</span> string-count result-string &lt;&gt;) all-possible-letters

<span style="color: #483d8b;">let</span>
<span style="color: #a020f0;">  : </span><span style="color: #0000ff;">maxOcc</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> max occurrences
<span style="color: #0000ff;">    minOcc</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> min occurrences
<span style="color: #0000ff;">  display</span> {maxOcc - minOcc}
</code></pre>
</div>

<p>
This is pretty slow. At 20 steps it takes two seconds to calculate 3
million elements and at 22 steps it’s already at 6 seconds for 12
million elements.
</p>

<p>
The second part needs 40 steps. I must change the approach.
</p>

<p>
Also I’m still kind of annoyed that reading the input usually takes a
too large fraction of the total code. I have the feeling that some
primitives are too low level in Scheme — need to fix that.
</p>

<p>
Consequence: I just wrote <code>string-split-substring</code> and if/once the
tests pass, I’ll submit it to Guile to ease the pain and use it in the
next step.
</p>
]]></description>
</item>
<item>
<title>Day 14, Puzzle 2: predict the element disbalance</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-14-puzzle-2</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-14-puzzle-2</guid>
<pubDate>Fri, 11 Nov 2022 20:40:00 +0100</pubDate>

<description><![CDATA[<p>
The answer actually only needs the counts of letters, so why should I
actually synthesize the polymer-string? Just having letter-bigrams
with their counts should avoid the algorithmic explosion.
</p>

<p>
But first let’s simplify the string input:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">snippet: {{{string-split-substring}}}</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-split-substring</span> str substring
  <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">equal?</span> substring <span style="color: #8b2252;">""</span>
<span style="color: #0000ff;">      map</span> string<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-&gt;list</span> str <span style="color: #b22222;">;; </span><span style="color: #b22222;">split each letter</span>
      <span style="color: #483d8b;">let</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> sublen<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-length</span> substring
        <span style="color: #483d8b;">let</span> lp<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">(start</span> <span style="color: #008b8b;">0</span>) (<span style="color: #0000ff;">res</span> <span style="color: #008b8b;">'()</span>)
<span style="color: #0000ff;">          cond</span>
<span style="color: #0000ff;">           (string-contains</span> str substring start) =&gt;
<span style="color: #0000ff;">             &#955;</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">end</span>
<span style="color: #0000ff;">                 lp</span> (<span style="color: #0000ff;">+</span> end sublen) (<span style="color: #0000ff;">cons</span> (<span style="color: #0000ff;">substring/shared</span> str start end) res)
<span style="color: #0000ff;">           else</span>
<span style="color: #0000ff;">             reverse!</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cons</span> (<span style="color: #0000ff;">substring/shared</span> str start) res
</code></pre>
</div>

<p>
This allows to simplify reading the input a bit:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">before</span>
<span style="color: #483d8b;">define</span> key-value
<span style="color: #0000ff;">  string-split</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-replace-substring</span> line <span style="color: #8b2252;">" -&gt; "</span> <span style="color: #8b2252;">";"</span>
<span style="color: #a020f0;">    . </span>#\<span style="color: #b22222;">;</span>
<span style="color: #b22222;">;; </span><span style="color: #b22222;">after</span>
<span style="color: #483d8b;">define</span> key-value
<span style="color: #0000ff;">  string-split-substring</span> line <span style="color: #8b2252;">" -&gt; "</span>
</code></pre>
</div>

<p>
To fix the algorithmic explosion, I’ll just not generate the polymer:
since nature already does it, why should I do it myself when all I
need are the resulting statistics? :-)
</p>

<p>
The simplest option is to use hash-maps and global mutation.
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">srfi</span> :1) take first second third fold drop-right
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> string-fun) string-replace-substring
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :26) cut

{{{map-over-lines-port}}}
{{{string-split-substring}}}

<span style="color: #483d8b;">define</span> letters<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">make-hash-table</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">letters-inc!</span> key value
<span style="color: #0000ff;">  hash-set!</span> letters key<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">+</span> value<span style="color: #a020f0;"> : </span><span style="color: #483d8b;">or</span> (<span style="color: #0000ff;">hash-ref</span> letters key) <span style="color: #008b8b;">0</span>

<span style="color: #483d8b;">define</span> pairs<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">make-hash-table</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pairs-inc!</span> key value
<span style="color: #0000ff;">  hash-set!</span> pairs key<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">+</span> value<span style="color: #a020f0;"> : </span><span style="color: #483d8b;">or</span> (<span style="color: #0000ff;">hash-ref</span> pairs key) <span style="color: #008b8b;">0</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pairs-dec!</span> key value
<span style="color: #0000ff;">  pairs-inc!</span> key<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">-</span> value

<span style="color: #483d8b;">define</span> input
  <span style="color: #483d8b;">let</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> port<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">open-input-file</span> <span style="color: #8b2252;">"advent-of-wisp-code-2021-d14p1-example-input.dat"</span>
    <span style="color: #b22222;">;; </span><span style="color: #b22222;">get the letters as before</span>
    <span style="color: #483d8b;">define</span> init
<span style="color: #0000ff;">        first</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map-over-lines/port</span> string-&gt;list port #:terminator <span style="color: #8b2252;">""</span>
    <span style="color: #b22222;">;; </span><span style="color: #b22222;">get the rules as before</span>
    <span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">split-line</span> line
        <span style="color: #483d8b;">define</span> key-value
<span style="color: #0000ff;">          string-split-substring</span> line <span style="color: #8b2252;">" -&gt; "</span>
<span style="color: #0000ff;">        cons</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-&gt;list</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">first</span> key-value
<span style="color: #0000ff;">               first</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-&gt;list</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">second</span> key-value
    <span style="color: #483d8b;">define</span> rules
<span style="color: #0000ff;">        map-over-lines/port</span> split-line port

    <span style="color: #b22222;">;; </span><span style="color: #b22222;">split the letters into pairs</span>
    <span style="color: #483d8b;">define</span> init-pairs
<span style="color: #0000ff;">        map</span> cons 
<span style="color: #0000ff;">          drop-right</span> init <span style="color: #008b8b;">1</span>
<span style="color: #0000ff;">          cdr</span> init
    <span style="color: #b22222;">;; </span><span style="color: #b22222;">track letters and pairs in the global hash-maps</span>
<span style="color: #0000ff;">    for-each</span> (<span style="color: #0000ff;">cut</span> letters-inc! &lt;&gt; <span style="color: #008b8b;">1</span>) init
<span style="color: #0000ff;">    for-each</span> (<span style="color: #0000ff;">cut</span> pairs-inc! &lt;&gt; <span style="color: #008b8b;">1</span>) init-pairs
<span style="color: #a020f0;">    . </span>rules

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply-rule</span> left right weight rules
  <span style="color: #483d8b;">define</span> pair<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cons</span> left right
  <span style="color: #483d8b;">define</span> matching<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">assoc</span> (<span style="color: #0000ff;">list</span> left right) rules
  <span style="color: #483d8b;">when</span> matching
    <span style="color: #483d8b;">let</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> middle<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cdr</span> matching
<span style="color: #0000ff;">      pairs-dec!</span> pair weight
<span style="color: #0000ff;">      pairs-inc!</span> (<span style="color: #0000ff;">cons</span> left middle) weight
<span style="color: #0000ff;">      pairs-inc!</span> (<span style="color: #0000ff;">cons</span> middle right) weight
<span style="color: #0000ff;">      letters-inc!</span> middle weight

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply-rules</span> rules
  <span style="color: #b22222;">;; </span><span style="color: #b22222;">get the items to fold over (avoid mutation while folding)</span>
  <span style="color: #483d8b;">define</span> letters-and-weights
<span style="color: #0000ff;">    hash-map-&gt;list</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">lambda</span> (<span style="color: #0000ff;">key</span> value)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">list</span> (<span style="color: #0000ff;">car</span> key) (<span style="color: #0000ff;">cdr</span> key) value
<span style="color: #a020f0;">      . </span>pairs
<span style="color: #0000ff;">  for-each</span> (<span style="color: #0000ff;">cut</span> apply-rule &lt;&gt; &lt;&gt; &lt;&gt; rules)
<span style="color: #0000ff;">    map</span> first letters-and-weights <span style="color: #b22222;">;; </span><span style="color: #b22222;">first</span>
<span style="color: #0000ff;">    map</span> second letters-and-weights <span style="color: #b22222;">;; </span><span style="color: #b22222;">second</span>
<span style="color: #0000ff;">    map</span> third letters-and-weights <span style="color: #b22222;">;; </span><span style="color: #b22222;">weight</span>

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply-rules-n-times</span> N rules
  <span style="color: #b22222;">;; </span><span style="color: #b22222;">simplified: no need for return values</span>
<span style="color: #0000ff;">  for-each</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;(x)</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply-rules</span> rules
<span style="color: #0000ff;">    iota</span> N

<span style="color: #0000ff;">apply-rules-n-times</span> <span style="color: #008b8b;">40</span> input

<span style="color: #483d8b;">define</span> occurrences
<span style="color: #0000ff;">  hash-map-&gt;list</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;(key</span> value) value
<span style="color: #a020f0;">    . </span>letters
<span style="color: #483d8b;">let</span>
<span style="color: #a020f0;">  : </span><span style="color: #0000ff;">maxOcc</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> max occurrences
<span style="color: #0000ff;">    minOcc</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> min occurrences
<span style="color: #0000ff;">  display</span> {maxOcc - minOcc}
</code></pre>
</div>

<p>
This now solves my speed problems: It takes 7 seconds for 10k steps.
The version from part 1 could only do 22 steps in that time.
</p>
]]></description>
</item>
<item>
<title>Day 15, Puzzle 1: Path planning</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-15-puzzle-1</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-15-puzzle-1</guid>
<pubDate>Mon, 14 Nov 2022 00:31:00 +0100</pubDate>

<description><![CDATA[<p>
Now we’re getting serious. Find the path with the lowest aggregated
cost of fields to enter. I need the globally best path, so the
obvious choice is <a href="https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm">Dijkstra's algorithm</a>.
</p>

<div class="org-src-container">
<pre class="src src-scheme"><code>1163751742
1381373672
2136511328
3694931569
7463417111
1319128137
1359912421
3125421639
1293138521
2311944581
</code></pre>
</div>

<p>
For Dijkstra I need a set of unvisited nodes and a set of visited
nodes. For simplicity I’ll start with plain lists of lists, the most
direct translation of the task, though that will not scale, so I will
likely have to change to a better datastructure in part 2.
</p>

<p>
The datastructure is a simple list of lists, defined by its accessors
<code>xy-ref</code> and <code>xy-set!</code>:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;;; </span><span style="color: #b22222;">snippet: {{{p15-xy-ref-and-set}}}</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">xy-ref</span> arr x y
<span style="color: #0000ff;">  list-ref</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">list-ref</span> arr y
<span style="color: #a020f0;">    . </span>x
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">xy-set!</span> arr x y val
<span style="color: #0000ff;">  list-set!</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">list-ref</span> arr y
<span style="color: #a020f0;">    . </span>x val
</code></pre>
</div>

<p>
In this naive approach, calculating the neighbors just looks around
in the datastructure.
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;;; </span><span style="color: #b22222;">snippet: {{{d15-neighbors}}}</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">neighbors</span> x y
  <span style="color: #483d8b;">define</span> dpos
<span style="color: #0000ff;">    '</span> (<span style="color: #0000ff;">-1</span> <span style="color: #008b8b;">0</span>) (<span style="color: #0000ff;">0</span> <span style="color: #008b8b;">-1</span>) (<span style="color: #0000ff;">+1</span> <span style="color: #008b8b;">0</span>) (<span style="color: #0000ff;">0</span> <span style="color: #008b8b;">+1</span>)
<span style="color: #0000ff;">  delete</span> <span style="color: #008b8b;">#f</span>
<span style="color: #0000ff;">    map</span>
<span style="color: #0000ff;">      &#955;</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">dx</span> dy
        <span style="color: #483d8b;">let</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">(xx</span> {x + dx}) (<span style="color: #0000ff;">yy</span> {y + dy})
          <span style="color: #483d8b;">and</span> {xx &gt;= 0} {xx &lt; len-x} {yy &gt;= 0} {yy &lt; len-y}
<span style="color: #0000ff;">            pos</span> {x + dx} {y + dy}
<span style="color: #0000ff;">      map</span> first dpos
<span style="color: #0000ff;">      map</span> second dpos
</code></pre>
</div>

<p>
Positions are tracked as records with x and y and distances use a
simple xy-structure:
</p>


<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;;; </span><span style="color: #b22222;">snippet: {{{d15-position-handling}}}</span>
<span style="color: #0000ff;">define-record-type</span> &lt;pos&gt;
<span style="color: #0000ff;">  pos</span> x y
<span style="color: #a020f0;">  . </span>pos?
<span style="color: #0000ff;">  x</span> pos-x
<span style="color: #0000ff;">  y</span> pos-y
<span style="color: #b22222;">;; </span><span style="color: #b22222;">Distances check x and y in a distances map:</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">distance</span> node
<span style="color: #0000ff;">  xy-ref</span> distances (<span style="color: #0000ff;">pos-x</span> node) (<span style="color: #0000ff;">pos-y</span> node)
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">distance-&lt;?</span> A B
<span style="color: #0000ff;">  &lt;</span>
<span style="color: #0000ff;">    distance</span> A
<span style="color: #0000ff;">    distance</span> B
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">calculate-distance</span> node current-distance
  <span style="color: #483d8b;">define</span> X<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pos-x</span> node
  <span style="color: #483d8b;">define</span> Y<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pos-y</span> node
  <span style="color: #483d8b;">define</span> path-cost<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">xy-ref</span> input X Y
  <span style="color: #483d8b;">define</span> known-distance<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">xy-ref</span> distances X Y
<span style="color: #0000ff;">  min</span> known-distance {current-distance + path-cost}
</code></pre>
</div>

<p>
Finding the closest node just iterates over all positions and keeps
the unvisited one with the shortest distance.
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">snippet: {{{d15-closest-unvisited-simple}}}</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">find-closest-unvisited-node</span>
  <span style="color: #483d8b;">define</span> len-x-1 {len-x - 1}
  <span style="color: #483d8b;">define</span> len-y-1 {len-y - 1}
  <span style="color: #483d8b;">let</span> loop<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">(x</span> <span style="color: #008b8b;">0</span>) (<span style="color: #0000ff;">y</span> <span style="color: #008b8b;">0</span>) (<span style="color: #0000ff;">closest-x</span> <span style="color: #008b8b;">0</span>) (<span style="color: #0000ff;">closest-y</span> <span style="color: #008b8b;">0</span>) (<span style="color: #0000ff;">closest-dist</span> (<span style="color: #0000ff;">inf</span>))
    <span style="color: #483d8b;">define</span> dist<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">distance</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pos</span> x y
    <span style="color: #483d8b;">define</span> unvisited<span style="color: #a020f0;"> : </span><span style="color: #483d8b;">not</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">xy-ref</span> visited x y
    <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #483d8b;">and</span> unvisited {dist &lt; closest-dist}
<span style="color: #0000ff;">      loop</span> x y x y dist
<span style="color: #0000ff;">      cond</span>
<span style="color: #a020f0;">        : </span><span style="color: #483d8b;">and</span> {len-x-1 &lt;= x} {len-y-1 &lt;= y}
          <span style="color: #483d8b;">if</span> unvisited
<span style="color: #0000ff;">            pos</span> closest-x closest-y
<span style="color: #a020f0;">            . </span><span style="color: #008b8b;">#f</span>
<span style="color: #0000ff;">        {len-x-1</span> &lt;= x}
<span style="color: #0000ff;">          loop</span> <span style="color: #008b8b;">0</span> {y + 1} closest-x closest-y closest-dist
<span style="color: #0000ff;">        else</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">loop</span> {x + 1} y closest-x closest-y closest-dist
</code></pre>
</div>

<p>
And processing one node just means calculating and setting the
distances of all its not yet visited neighbors:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">snippet: {{{d15-visit-current-node-simple}}}</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">visit-current-node</span>
  <span style="color: #483d8b;">define</span> neigh <span style="color: #b22222;">;; </span><span style="color: #b22222;">all unvisited neighbors</span>
<span style="color: #0000ff;">    remove</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;</span> (<span style="color: #0000ff;">node</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">xy-ref</span> visited (<span style="color: #0000ff;">pos-x</span> node) (<span style="color: #0000ff;">pos-y</span> node)
<span style="color: #0000ff;">      neighbors</span> (<span style="color: #0000ff;">pos-x</span> current-node) (<span style="color: #0000ff;">pos-y</span> current-node)
  <span style="color: #483d8b;">define</span> current-distance
<span style="color: #0000ff;">    xy-ref</span> distances (<span style="color: #0000ff;">pos-x</span> current-node) (<span style="color: #0000ff;">pos-y</span> current-node)
<span style="color: #0000ff;">  for-each</span>
<span style="color: #0000ff;">    &#955;</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">node</span>
<span style="color: #a020f0;">      . </span><span style="color: #008b8b;">#f</span>
<span style="color: #0000ff;">      xy-set!</span> distances
<span style="color: #0000ff;">         pos-x</span> node
<span style="color: #0000ff;">         pos-y</span> node
<span style="color: #0000ff;">         calculate-distance</span> node current-distance
<span style="color: #a020f0;">    . </span>neigh
<span style="color: #0000ff;">  xy-set!</span> visited (<span style="color: #0000ff;">pos-x</span> current-node) (<span style="color: #0000ff;">pos-y</span> current-node) <span style="color: #008b8b;">#t</span>
<span style="color: #0000ff;">  and=&gt;</span> (<span style="color: #0000ff;">find-closest-unvisited-node</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cut</span> <span style="color: #483d8b;">set!</span> current-node &lt;&gt;
</code></pre>
</div>

<p>
To put it all together:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> pretty-print) pretty-print
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> optargs) define*
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :26) cut
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :9) define-record-type
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :1) first second append-map remove

{{{map-over-lines}}}
{{{string-split-substring}}}

<span style="color: #b22222;">;; </span><span style="color: #b22222;">use the new string-split-substring function</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">line-&gt;numbers</span> line
<span style="color: #0000ff;">  map</span> string-&gt;number<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-split-substring</span> line <span style="color: #8b2252;">""</span>

<span style="color: #483d8b;">define</span> input
<span style="color: #0000ff;">  map-over-lines</span> line-&gt;numbers <span style="color: #8b2252;">"advent-of-wisp-code-2021-d15p1-example-input.dat"</span>

<span style="color: #483d8b;">define</span> len-y<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">length</span> input
<span style="color: #483d8b;">define</span> len-x<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">length</span> (<span style="color: #0000ff;">list-ref</span> input <span style="color: #008b8b;">0</span>)

{{{p15-xy-ref-and-set}}}

<span style="color: #483d8b;">define</span> visited
<span style="color: #0000ff;">  map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;(y)</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> (<span style="color: #0000ff;">&#955;(x</span>) <span style="color: #008b8b;">#f</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">iota</span> len-x
<span style="color: #0000ff;">        iota</span> len-y
<span style="color: #483d8b;">define</span> distances
<span style="color: #0000ff;">  map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;(y)</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> (<span style="color: #0000ff;">&#955;(x</span>) (<span style="color: #0000ff;">inf</span>))<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">iota</span> len-x
<span style="color: #0000ff;">        iota</span> len-y
<span style="color: #b22222;">;; </span><span style="color: #b22222;">init the risk of the first node as 0</span>
<span style="color: #0000ff;">xy-set!</span> distances <span style="color: #008b8b;">0</span> <span style="color: #008b8b;">0</span> <span style="color: #008b8b;">0</span>

{{{d15-position-handling}}}
{{{d15-neighbors}}}

<span style="color: #483d8b;">define</span> initial-node <span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pos</span> <span style="color: #008b8b;">0</span> <span style="color: #008b8b;">0</span>
<span style="color: #483d8b;">define</span> target-node<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pos</span> {len-x - 1} {len-y - 1}
<span style="color: #483d8b;">define</span> current-node initial-node

{{{d15-closest-unvisited-simple}}}

{{{d15-visit-current-node-simple}}}

<span style="color: #483d8b;">while</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">visit-current-node</span>
<span style="color: #a020f0;">  . </span><span style="color: #008b8b;">#f</span>

<span style="color: #b22222;">;; </span><span style="color: #b22222;">Now the cost of all shortest paths to all nodes is known.</span>
<span style="color: #b22222;">;; </span><span style="color: #b22222;">The lowest total risk is just the distance to the target</span>
<span style="color: #0000ff;">pretty-print</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">distance</span> target-node
</code></pre>
</div>

<p>
That finished with the real input in less than one minute despite the
sub-par datastructures used here.
</p>
]]></description>
</item>
<item>
<title>Day 15, Puzzle 2: Larger path planning</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-15-puzzle-2</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-15-puzzle-2</guid>
<pubDate>Fri, 18 Nov 2022 00:33:00 +0100</pubDate>

<description><![CDATA[<p>
As expected, the second task has a larger map. More exactly: a 25x larger map.
</p>

<p>
I need better datastructures. But the first step is profiling:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">add here all the code before calling visit-current-node with the real code</span>
<span style="color: #0000ff;">,profile</span> <span style="color: #483d8b;">while</span> (<span style="color: #0000ff;">visit-current-node</span>) <span style="color: #008b8b;">#f</span>
</code></pre>
</div>

<pre class="example" id="org983e010">
%     cumulative   self             
time   seconds     seconds  procedure
 71.06     27.98     27.98  list-ref
 13.18     39.19      5.19  find-closest-unvisited-node
  6.16      2.43      2.43  distance
  5.95     15.86      2.34  xy-ref
  3.38      1.33      1.33  %after-gc-thunk
  0.09     39.35      0.03  visit-current-node
  0.04     39.38      0.02  anon #x18f2be8
  0.04      0.02      0.02  &lt;current input&gt;:82:0
  0.04      0.02      0.02  xy-set!
  0.04      0.02      0.02  ice-9/boot-9.scm:812:0:and=&gt;
  0.00      1.33      0.00  anon #xf88160
  0.00      0.07      0.00  ice-9/boot-9.scm:253:2:for-each
  0.00      0.07      0.00  &lt;current input&gt;:112:0
  0.00      0.02      0.00  remove
  0.00      0.02      0.00  neighbors
  0.00      0.02      0.00  ice-9/boot-9.scm:230:5:map2
</pre>

<p>
The culprits are obvious: <code>list-ref</code> and <code>find-closest-unvisited-node</code>.
</p>

<p>
The reason is clear: list-ref on the linked lists scales linearly:
<code>O(N)</code>. Once it is taken out, the next target for optimization is
<code>find-closest-unvisited-node</code>: it currently looks at all nodes, so it
also scales at best in the number of list-access: <code>O(N) * list-ref</code>.
Since it is needed once per node in Dijkstra, the total algorithmic
cost of this naive implementation is at least cubic:
</p>

<pre class="example">
O(N) * find-closest-unvisited-node * list-ref ~ O(N³)
</pre>

<p>
But first: let’s check whether just switching to a vector is enough.
With 25x the nodes, quadratic scaling would mean 625x the runtime.
Vectors already reduce the runtime for the unchanged input to 17s, so
this could finish in 3 hours.
</p>

<p>
Change: Use 25x the nodes:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;;;</span><span style="color: #b22222;">snippet: {{{d15p2-5x-input}}}</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">inc</span> number
  <span style="color: #483d8b;">let</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> num {number + 1}
    <span style="color: #483d8b;">if</span> {num &gt; 9} <span style="color: #008b8b;">1</span> num
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">inc-list</span> L
<span style="color: #0000ff;">  map</span> inc L

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">5x-line</span> line
  <span style="color: #483d8b;">define</span> nextline line
  <span style="color: #483d8b;">let</span> loop<span style="color: #a020f0;"> : </span> (<span style="color: #0000ff;">n</span> <span style="color: #008b8b;">4</span>) (<span style="color: #0000ff;">line</span> line)
    <span style="color: #483d8b;">set!</span> nextline<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> inc nextline
    <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">zero?</span> n
<span style="color: #a020f0;">       . </span>line
<span style="color: #0000ff;">       loop</span> {n - 1}<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">append</span> line nextline
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">5x-arr</span> arr
  <span style="color: #483d8b;">define</span> nextarr arr
  <span style="color: #483d8b;">let</span> loop<span style="color: #a020f0;"> : </span> (<span style="color: #0000ff;">n</span> <span style="color: #008b8b;">4</span>) (<span style="color: #0000ff;">arr</span> arr)
    <span style="color: #483d8b;">set!</span> nextarr<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> inc-list nextarr
    <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">zero?</span> n
<span style="color: #a020f0;">       . </span>arr
<span style="color: #0000ff;">       loop</span> {n - 1}<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">append</span> arr nextarr
<span style="color: #b22222;">;; </span><span style="color: #b22222;">5x each line</span>
<span style="color: #483d8b;">set!</span> input<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> 5x-line input
<span style="color: #b22222;">;; </span><span style="color: #b22222;">5x the input, in lazy mode</span>
<span style="color: #483d8b;">set!</span> input<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">5x-arr</span> input
</code></pre>
</div>

<p>
Change: Use a vector. Change the data to vectors and adjust <code>xy-ref</code> and
<code>xy-set!</code>.
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">snippet:  {{{d15p2-move-to-vector}}}</span>
<span style="color: #b22222;">;; </span><span style="color: #b22222;">move to a vector</span>
<span style="color: #483d8b;">set!</span> input
<span style="color: #0000ff;">  list-&gt;vector</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> list-&gt;vector input

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">xy-ref</span> arr x y
<span style="color: #0000ff;">  vector-ref</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">vector-ref</span> arr y
<span style="color: #a020f0;">    . </span>x
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">xy-set!</span> arr x y val
<span style="color: #0000ff;">  vector-set!</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">vector-ref</span> arr y
<span style="color: #a020f0;">    . </span>x val

<span style="color: #b22222;">;; </span><span style="color: #b22222;">move to a vector</span>
<span style="color: #483d8b;">define</span> visited
<span style="color: #0000ff;"> list-&gt;vector</span>
<span style="color: #0000ff;">  map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;(y)</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">list-&gt;vector</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> (<span style="color: #0000ff;">&#955;(x</span>) <span style="color: #008b8b;">#f</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">iota</span> len-x
<span style="color: #0000ff;">        iota</span> len-y
<span style="color: #483d8b;">define</span> distances
<span style="color: #0000ff;"> list-&gt;vector</span>
<span style="color: #0000ff;">  map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;(y)</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">list-&gt;vector</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> (<span style="color: #0000ff;">&#955;(x</span>) (<span style="color: #0000ff;">inf</span>))<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">iota</span> len-x
<span style="color: #0000ff;">        iota</span> len-y
</code></pre>
</div>

<p>
That’s all the changes: the other snippets stay the same. Putting it
all together (re-using snippets from part 1):
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> pretty-print) pretty-print
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> optargs) define*
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :26) cut
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :9) define-record-type
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :1) first second append-map remove

{{{map-over-lines}}}
{{{string-split-substring}}}

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">line-&gt;numbers</span> line
<span style="color: #0000ff;">  map</span> string-&gt;number<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-split-substring</span> line <span style="color: #8b2252;">""</span>
<span style="color: #483d8b;">define</span> input
<span style="color: #0000ff;">  map-over-lines</span> line-&gt;numbers <span style="color: #8b2252;">"advent-of-wisp-code-2021-d15p1-example-input.dat"</span>

<span style="color: #b22222;">;; </span><span style="color: #b22222;">change: use 5x the input</span>
{{{d15p2-5x-input}}}

<span style="color: #483d8b;">define</span> len-y<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">length</span> input
<span style="color: #483d8b;">define</span> len-x<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">length</span> (<span style="color: #0000ff;">list-ref</span> input <span style="color: #008b8b;">0</span>)

<span style="color: #b22222;">;; </span><span style="color: #b22222;">change: use a vector instead of a list</span>
{{{d15p2-move-to-vector}}}

<span style="color: #b22222;">;; </span><span style="color: #b22222;">init the risk of the first node as 0</span>
<span style="color: #0000ff;">xy-set!</span> distances <span style="color: #008b8b;">0</span> <span style="color: #008b8b;">0</span> <span style="color: #008b8b;">0</span>

{{{d15-position-handling}}}
{{{d15-neighbors}}}

<span style="color: #483d8b;">define</span> initial-node <span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pos</span> <span style="color: #008b8b;">0</span> <span style="color: #008b8b;">0</span>
<span style="color: #483d8b;">define</span> target-node<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pos</span> {len-x - 1} {len-y - 1}
<span style="color: #483d8b;">define</span> current-node initial-node

<span style="color: #0000ff;">{{{d15-closest-unvisited-simple}}}</span>        

{{{d15-visit-current-node-simple}}}

<span style="color: #483d8b;">while</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">visit-current-node</span>
<span style="color: #a020f0;">  . </span><span style="color: #008b8b;">#f</span>

<span style="color: #b22222;">;; </span><span style="color: #b22222;">Now the cost of all shortest paths to all nodes is known.</span>
<span style="color: #b22222;">;; </span><span style="color: #b22222;">The lowest total risk is just the distance to the target</span>
<span style="color: #0000ff;">pretty-print</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">distance</span> target-node
</code></pre>
</div>

<p>
Yes, it works. Slow, but fast enough to finish. That’s the power of
just switching out the basic datastructure for one that’s better
suited for the task. Don’t use a linked list, if you want to access
elements at arbitrary positions by index.
</p>

<p>
With this, the task is done, but not yet done <i>well</i>.
</p>
<div id="outline-container-day-15-puzzle-2-pq" class="outline-3">
<h3 id="day-15-puzzle-2-pq">Simple Priority Queue</h3>
<div class="outline-text-3" id="text-day-15-puzzle-2-pq">
<p>
The next step is changing <code>find-closest-unvisited-node</code> to use a
priority queue.
</p>

<p>
I’ll have to implement a Fibonacci heap — or one of the <a href="https://en.wikipedia.org/wiki/Fibonacci_heap#Summary_of_running_times">other priority queues with sufficient scaling</a>.
</p>

<p>
Likely I should try a Strict Fibonacci heap for the best scaling (<a href="https://www.cs.au.dk/~gerth/papers/stoc12.pdf">Brodal, Gerth Stølting; Lagogiannis, George; Tarjan, Robert E., 2012</a>), or one of the queues with best empirical results  (<a href="https://arxiv.org/abs/1403.0252">Daniel H. Larkin, Siddhartha Sen, Robert E. Tarjan, 2014</a>).
</p>

<p>
But that requires thinking in trees, so let’s make the simplest
priority queue instead. The scaling will not suffice for hard
challenges, but it should suffice for this Dijkstra — and keep it
simple. The data holder is a plain list for starters and ordering is
done by simply sorting after every insert and searching the list
linearly when decreasing, because there a value has to be moved.
</p>

<p>
The algorithm uses a slowly moving front of open nodes of roughly
<code>O(sqrt N)</code> size, and it kind of follows the natural ordering of the
elements, so the scaling of the priority queue for the task at hand
may actually be <code>O(sqrt N)</code>.
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">snippet {{{priority-queue}}}</span>
<span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> pretty-print) pretty-print
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :9) define-record-type
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :1) take

<span style="color: #0000ff;">define-record-type</span> &lt;queue-item&gt;
<span style="color: #0000ff;">    queue-item</span> priority value
<span style="color: #a020f0;">    . </span>queue-item?
<span style="color: #0000ff;">    priority</span> queue-item-priority queue-item-priority-set!
<span style="color: #0000ff;">    value</span> queue-item-value

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">make-priority-queue</span>
<span style="color: #a020f0;">       . </span><span style="color: #008b8b;">'()</span> <span style="color: #b22222;">;; </span><span style="color: #b22222;">plain linked list</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pq-find-min</span> q
    <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">null?</span> q
<span style="color: #a020f0;">       . </span><span style="color: #008b8b;">#f</span>
<span style="color: #0000ff;">       queue-item-value</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">car</span> q
<span style="color: #483d8b;">define</span> pq-delete-min cdr
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pq-sort</span> q
<span style="color: #0000ff;">    sort</span> q<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;</span> (<span style="color: #0000ff;">a</span> b)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&lt;</span> (<span style="color: #0000ff;">queue-item-priority</span> a) (<span style="color: #0000ff;">queue-item-priority</span> b)
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pq-insert</span> q q-item
<span style="color: #0000ff;">    and=&gt;</span> (<span style="color: #0000ff;">cons</span> q-item q) pq-sort
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pq-decrease</span> q priority q-item-value
<span style="color: #a020f0;">    . </span><span style="color: #8b2252;">"This has linear time: O(N).</span>

<span style="color: #8b2252;">    For a proper priority queue it should have O(log n) or O(1)."</span>
    <span style="color: #483d8b;">let</span> loop<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">(item</span> (<span style="color: #0000ff;">car</span> q)) (<span style="color: #0000ff;">before</span> <span style="color: #008b8b;">'()</span>) (<span style="color: #0000ff;">after</span> <span style="color: #008b8b;">'()</span>) (<span style="color: #0000ff;">rest</span> (<span style="color: #0000ff;">cdr</span> q))
<span style="color: #0000ff;">        cond</span>
<span style="color: #a020f0;">          : </span><span style="color: #0000ff;">equal?</span> q-item-value<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">queue-item-value</span> item
            <span style="color: #b22222;">;; </span><span style="color: #b22222;">use mutating functions (!) for efficiency</span>
<span style="color: #0000ff;">            append!</span>
<span style="color: #0000ff;">              reverse!</span> before
<span style="color: #0000ff;">              cons</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">queue-item</span> priority q-item-value
<span style="color: #0000ff;">                     reverse!</span> after
<span style="color: #a020f0;">              . </span>rest
<span style="color: #a020f0;">          : </span><span style="color: #0000ff;">null?</span> rest
<span style="color: #0000ff;">            error</span> <span style="color: #8b2252;">"item not found in q:"</span> q-item-value<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">take</span> q <span style="color: #008b8b;">10</span>
          <span style="color: #b22222;">;; </span><span style="color: #b22222;">the &lt;= is required to have stable sorting.</span>
<span style="color: #0000ff;">          {</span> (<span style="color: #0000ff;">queue-item-priority</span> item) &lt;= priority }
<span style="color: #0000ff;">             loop</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">car</span> rest
<span style="color: #0000ff;">                    cons</span> item before
<span style="color: #a020f0;">                    . </span>after
<span style="color: #0000ff;">                    cdr</span> rest
<span style="color: #0000ff;">          else</span>
<span style="color: #0000ff;">             loop</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">car</span> rest
<span style="color: #a020f0;">                    . </span>before
<span style="color: #0000ff;">                    cons</span> item after
<span style="color: #0000ff;">                    cdr</span> rest
</code></pre>
</div>

<p>
Now I use the priority queue to track the unvisited nodes and get
the closest one:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">snippet {{{priority-queue-usage-unvisited}}}</span>
<span style="color: #b22222;">;; </span><span style="color: #b22222;">priority-queue: unvisited (this should decrease the cost)</span>
<span style="color: #483d8b;">define</span> unvisited
<span style="color: #0000ff;">  append-map</span>
<span style="color: #0000ff;">    &#955;</span> (<span style="color: #0000ff;">x</span>)
<span style="color: #0000ff;">      map</span>
<span style="color: #0000ff;">        &#955;</span> (<span style="color: #0000ff;">y</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">queue-item</span> (<span style="color: #0000ff;">inf</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pos</span> x y
<span style="color: #0000ff;">        iota</span> len-y
<span style="color: #0000ff;">    iota</span> len-x

<span style="color: #b22222;">;; </span><span style="color: #b22222;">With the priority queue, this is down to a single line.</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">find-closest-unvisited-node</span>
<span style="color: #0000ff;">  pq-find-min</span> unvisited

</code></pre>
</div>

<p>
Processing the current node not only sets the by position, but also
changes the distance inside the priority queue and takes the next node
to process from it:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">snippet {{{priority-queue-usage-visit-current-node}}}</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">visit-current-node</span>
  <span style="color: #483d8b;">define</span> neigh <span style="color: #b22222;">;; </span><span style="color: #b22222;">all unvisited neighbors</span>
<span style="color: #0000ff;">    remove</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;</span> (<span style="color: #0000ff;">node</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">xy-ref</span> visited (<span style="color: #0000ff;">pos-x</span> node) (<span style="color: #0000ff;">pos-y</span> node)
<span style="color: #0000ff;">      neighbors</span> (<span style="color: #0000ff;">pos-x</span> current-node) (<span style="color: #0000ff;">pos-y</span> current-node)
  <span style="color: #483d8b;">define</span> current-distance
<span style="color: #0000ff;">    xy-ref</span> distances (<span style="color: #0000ff;">pos-x</span> current-node) (<span style="color: #0000ff;">pos-y</span> current-node)
<span style="color: #0000ff;">  for-each</span>
<span style="color: #0000ff;">    &#955;</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">node</span>
      <span style="color: #483d8b;">let</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> d<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">calculate-distance</span> node current-distance
        <span style="color: #483d8b;">set!</span> unvisited<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pq-decrease</span> unvisited d node
<span style="color: #0000ff;">        xy-set!</span> distances
<span style="color: #0000ff;">           pos-x</span> node
<span style="color: #0000ff;">           pos-y</span> node
<span style="color: #a020f0;">           . </span>d
<span style="color: #a020f0;">    . </span>neigh
<span style="color: #0000ff;">  xy-set!</span> visited (<span style="color: #0000ff;">pos-x</span> current-node) (<span style="color: #0000ff;">pos-y</span> current-node) <span style="color: #008b8b;">#t</span>
  <span style="color: #b22222;">;; </span><span style="color: #b22222;">delete the current-node</span>
  <span style="color: #483d8b;">set!</span> unvisited<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pq-delete-min</span> unvisited
<span style="color: #0000ff;">  and=&gt;</span> (<span style="color: #0000ff;">find-closest-unvisited-node</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cut</span> <span style="color: #483d8b;">set!</span> current-node &lt;&gt;

</code></pre>
</div>

<p>
Putting the full Dijkstra together again, now with the priority queue:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> pretty-print) pretty-print
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> optargs) define*
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :26) cut
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :9) define-record-type
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :1) first second append-map remove take

{{{map-over-lines}}}
{{{string-split-substring}}}
{{{priority-queue}}}

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">line-&gt;numbers</span> line
<span style="color: #0000ff;">  map</span> string-&gt;number<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-split-substring</span> line <span style="color: #8b2252;">""</span>

<span style="color: #483d8b;">define</span> input
<span style="color: #0000ff;">  map-over-lines</span> line-&gt;numbers <span style="color: #8b2252;">"advent-of-wisp-code-2021-d15p1-example-input.dat"</span>

{{{d15p2-5x-input}}}

<span style="color: #483d8b;">define</span> len-y<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">length</span> input
<span style="color: #483d8b;">define</span> len-x<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">length</span> (<span style="color: #0000ff;">list-ref</span> input <span style="color: #008b8b;">0</span>)

{{{d15p2-move-to-vector}}}

<span style="color: #b22222;">;; </span><span style="color: #b22222;">init the risk of the first node as 0</span>
<span style="color: #0000ff;">xy-set!</span> distances <span style="color: #008b8b;">0</span> <span style="color: #008b8b;">0</span> <span style="color: #008b8b;">0</span>

{{{d15-position-handling}}}

{{{d15-neighbors}}}

<span style="color: #483d8b;">define</span> initial-node <span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pos</span> <span style="color: #008b8b;">0</span> <span style="color: #008b8b;">0</span>
<span style="color: #483d8b;">define</span> target-node<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pos</span> {len-x - 1} {len-y - 1}
<span style="color: #483d8b;">define</span> current-node initial-node

{{{priority-queue-usage-unvisited}}}
<span style="color: #483d8b;">set!</span> unvisited<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pq-decrease</span> unvisited <span style="color: #008b8b;">0</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pos</span> <span style="color: #008b8b;">0</span> <span style="color: #008b8b;">0</span>

{{{priority-queue-usage-visit-current-node}}}

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cost-to-target</span>
  <span style="color: #483d8b;">while</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">visit-current-node</span>
<span style="color: #a020f0;">    . </span><span style="color: #008b8b;">#f</span>
<span style="color: #0000ff;">  distance</span> target-node

<span style="color: #b22222;">;; </span><span style="color: #b22222;">Now the cost of all shortest paths to all nodes is known.</span>
<span style="color: #b22222;">;; </span><span style="color: #b22222;">The lowest total risk is just the distance to the target</span>
<span style="color: #0000ff;">pretty-print</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cost-to-target</span>
</code></pre>
</div>

<p>
Using this trivial priority queue, we’re down from 2h with the naive
search on the raw map-data to 11 minutes. The algorithmic cost is
dominated by pq-decrease, so using a better priority-queue could
decrease the cost a lot:
</p>

<pre class="example" id="orgf77644d">
,profile cost-to-target .
%     cumulative   self             
time   seconds     seconds  procedure
 81.49    883.98    734.70  pq-decrease
  6.49     58.50     58.50  %after-gc-thunk
  6.45     58.11     58.11  reverse!
  3.63     32.70     32.70  equal?
  1.73     15.58     15.56  append!
  0.03    900.08      0.30  &lt;current input&gt;:185:0
  0.03      0.28      0.28  &lt;current input&gt;:203:8
  0.03      0.24      0.24  xy-ref
  0.02    901.51      0.19  visit-current-node
  0.02      0.15      0.15  &lt;current input&gt;:160:0
  0.01      0.13      0.13  xy-set!
  0.01      0.56      0.11  neighbors
  0.01      0.54      0.11  ice-9/boot-9.scm:230:5:map2
  0.01      0.09      0.09  min
  0.01    900.25      0.06  ice-9/boot-9.scm:253:2:for-each
  0.01      0.06      0.06  cadr
  0.00      0.26      0.04  ice-9/boot-9.scm:220:5:map1
  0.00      0.04      0.04  pq-delete-min
</pre>
</div>
</div>
<div id="outline-container-day-15-puzzle-2-pfds" class="outline-3">
<h3 id="day-15-puzzle-2-pfds">Purely Functional Priority Search Queue</h3>
<div class="outline-text-3" id="text-day-15-puzzle-2-pfds">
<p>
Redefining the priority queue with the Priority Search Queue from the
<a href="https://github.com/ijp/pfds">Purely Functional Data Structures</a> should give us much better
performance. Let’s try that:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">snippet {{{priority-queue-pfds}}}</span>
<span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> pretty-print) pretty-print
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :26) cut
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :9) define-record-type
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :1) take
<span style="color: #0000ff;">         pfds</span> psqs <span style="color: #b22222;">;; </span><span style="color: #b22222;">Priority Search Queue</span>

<span style="color: #0000ff;">define-record-type</span> &lt;queue-item&gt;
<span style="color: #0000ff;">    queue-item</span> priority value
<span style="color: #a020f0;">    . </span>queue-item?
<span style="color: #0000ff;">    priority</span> queue-item-priority queue-item-priority-set!
<span style="color: #0000ff;">    value</span> queue-item-value
<span style="color: #b22222;">;; </span><span style="color: #b22222;">the position comparator defines the traversal order</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pos-&lt;?</span> p0 p1
  <span style="color: #483d8b;">define</span> x0<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pos-x</span> p0
  <span style="color: #483d8b;">define</span> y0<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pos-y</span> p0
  <span style="color: #483d8b;">define</span> x1<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pos-x</span> p1
  <span style="color: #483d8b;">define</span> y1<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pos-y</span> p1
  <span style="color: #483d8b;">if</span> {x0 = x1} {y0 &lt; y1} {x0 &lt; x1}
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">make-priority-queue</span>
<span style="color: #0000ff;">       make-psq</span> pos-&lt;? &lt;
<span style="color: #483d8b;">define</span> pq-find-min psq-min
<span style="color: #483d8b;">define</span> pq-delete-min psq-delete-min
<span style="color: #483d8b;">define</span> pq-delete psq-delete
<span style="color: #483d8b;">define</span> pq-insert psq-set
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pq-decrease</span> q priority q-item-value
<span style="color: #0000ff;">    psq-update</span> q q-item-value 
<span style="color: #0000ff;">      &#955;</span> (<span style="color: #0000ff;">prio</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">min</span> priority prio
<span style="color: #a020f0;">      . </span>priority

</code></pre>
</div>

<p>
We’ll have to adjust the creation of the unvisited node queue:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">snippet {{{priority-queue-usage-unvisited-pfds}}}</span>
<span style="color: #b22222;">;; </span><span style="color: #b22222;">priority-queue: unvisited (this should decrease the cost)</span>
<span style="color: #483d8b;">define</span> unvisited
<span style="color: #0000ff;">  fold</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;</span> (<span style="color: #0000ff;">next</span> previous)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pq-insert</span> previous next<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">inf</span>
<span style="color: #0000ff;">       make-priority-queue</span>
<span style="color: #0000ff;">       append-map</span>
<span style="color: #0000ff;">         &#955;</span> (<span style="color: #0000ff;">x</span>)
<span style="color: #0000ff;">           map</span>
<span style="color: #0000ff;">             &#955;</span> (<span style="color: #0000ff;">y</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pos</span> x y
<span style="color: #0000ff;">             iota</span> len-y
<span style="color: #0000ff;">         iota</span> len-x
<span style="color: #b22222;">;; </span><span style="color: #b22222;">With the priority queue, this is down to a single line.</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">find-closest-unvisited-node</span>
  <span style="color: #483d8b;">and</span>
    <span style="color: #483d8b;">not</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">psq-empty?</span> unvisited
<span style="color: #0000ff;">    pq-find-min</span> unvisited

</code></pre>
</div>

<p>
And delete the minimum node before adjusting other nodes to avoid an infinite loop:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">snippet {{{priority-queue-usage-visit-current-node-pfds}}}</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">visit-current-node</span>
  <span style="color: #483d8b;">define</span> neigh <span style="color: #b22222;">;; </span><span style="color: #b22222;">all unvisited neighbors</span>
<span style="color: #0000ff;">    remove</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;</span> (<span style="color: #0000ff;">node</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">xy-ref</span> visited (<span style="color: #0000ff;">pos-x</span> node) (<span style="color: #0000ff;">pos-y</span> node)
<span style="color: #0000ff;">      neighbors</span> (<span style="color: #0000ff;">pos-x</span> current-node) (<span style="color: #0000ff;">pos-y</span> current-node)

  <span style="color: #483d8b;">define</span> current-distance
<span style="color: #0000ff;">    xy-ref</span> distances (<span style="color: #0000ff;">pos-x</span> current-node) (<span style="color: #0000ff;">pos-y</span> current-node)
  <span style="color: #b22222;">;; </span><span style="color: #b22222;">delete the current-node from unvisited</span>
  <span style="color: #483d8b;">set!</span> unvisited<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pq-delete-min</span> unvisited

<span style="color: #0000ff;">  for-each</span>
<span style="color: #0000ff;">    &#955;</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">node</span>
      <span style="color: #483d8b;">let</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> d<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">calculate-distance</span> node current-distance
        <span style="color: #483d8b;">set!</span> unvisited<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pq-decrease</span> unvisited d node
<span style="color: #0000ff;">        xy-set!</span> distances
<span style="color: #0000ff;">           pos-x</span> node
<span style="color: #0000ff;">           pos-y</span> node
<span style="color: #a020f0;">           . </span>d
<span style="color: #a020f0;">    . </span>neigh

<span style="color: #0000ff;">  xy-set!</span> visited (<span style="color: #0000ff;">pos-x</span> current-node) (<span style="color: #0000ff;">pos-y</span> current-node) <span style="color: #008b8b;">#t</span>
<span style="color: #0000ff;">  and=&gt;</span> (<span style="color: #0000ff;">find-closest-unvisited-node</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cut</span> <span style="color: #483d8b;">set!</span> current-node &lt;&gt;

</code></pre>
</div>

<p>
But overall the changes are pretty minor:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">ice-9</span> rdelim) read-line
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> pretty-print) pretty-print
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> optargs) define*
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :26) cut
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :9) define-record-type
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :1) first second append-map remove take fold
<span style="color: #0000ff;">         pfds</span> psqs <span style="color: #b22222;">;; </span><span style="color: #b22222;">Priority Search Queue</span>

{{{map-over-lines}}}
{{{string-split-substring}}}


<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">line-&gt;numbers</span> line
<span style="color: #0000ff;">  map</span> string-&gt;number<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">string-split-substring</span> line <span style="color: #8b2252;">""</span>

<span style="color: #483d8b;">define</span> input
<span style="color: #0000ff;">  map-over-lines</span> line-&gt;numbers <span style="color: #8b2252;">"advent-of-wisp-code-2021-d15p1-example-input.dat"</span>

{{{d15p2-5x-input}}}

<span style="color: #483d8b;">define</span> len-y<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">length</span> input
<span style="color: #483d8b;">define</span> len-x<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">length</span> (<span style="color: #0000ff;">list-ref</span> input <span style="color: #008b8b;">0</span>)

{{{d15p2-move-to-vector}}}

<span style="color: #b22222;">;; </span><span style="color: #b22222;">init the risk of the first node as 0</span>
<span style="color: #0000ff;">xy-set!</span> distances <span style="color: #008b8b;">0</span> <span style="color: #008b8b;">0</span> <span style="color: #008b8b;">0</span>

{{{d15-position-handling}}}

{{{priority-queue-pfds}}}
{{{priority-queue-usage-unvisited-pfds}}}
{{{d15-neighbors}}}

<span style="color: #483d8b;">define</span> initial-node <span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pos</span> <span style="color: #008b8b;">0</span> <span style="color: #008b8b;">0</span>
<span style="color: #483d8b;">define</span> target-node<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pos</span> {len-x - 1} {len-y - 1}
<span style="color: #483d8b;">define</span> current-node initial-node

<span style="color: #483d8b;">set!</span> unvisited<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pq-decrease</span> unvisited <span style="color: #008b8b;">0</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">pos</span> <span style="color: #008b8b;">0</span> <span style="color: #008b8b;">0</span>

{{{priority-queue-usage-visit-current-node-pfds}}}

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cost-to-target</span>
  <span style="color: #483d8b;">while</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">visit-current-node</span>
<span style="color: #a020f0;">    . </span><span style="color: #008b8b;">#t</span>
<span style="color: #0000ff;">  distance</span> target-node

<span style="color: #b22222;">;; </span><span style="color: #b22222;">Now the cost of all shortest paths to all nodes is known.</span>
<span style="color: #b22222;">;; </span><span style="color: #b22222;">The lowest total risk is just the distance to the target</span>
<span style="color: #0000ff;">pretty-print</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cost-to-target</span>
</code></pre>
</div>

<p>
This code now takes only <b>10 seconds</b> for completion instead of <b>8
minutes</b>. 
</p>

<p>
<i>The difference of the previous version compared to the earlier
results are due to faster hardware.</i>
</p>


<pre class="example" id="org7f451e2">
wisp@(guile-user)&gt; ,profile cost-to-target 
... 
... 

%     cumulative   self             
time   seconds     seconds  procedure
 29.36      4.10      4.10  struct-ref
 15.65      4.08      2.19  ice-9/boot-9.scm:1211:8
 14.46      6.33      2.02  rnrs/records/procedural.scm:141:6
  5.37      1.89      0.75  ice-9/boot-9.scm:978:0:record-type-parents
  4.32      0.75      0.60  ice-9/boot-9.scm:1169:19
  4.17      0.71      0.58  pfds/psqs.sls:235:0:update
  3.28      7.37      0.46  pfds/psqs.sls:149:0:play-match
  2.68      2.69      0.37  pfds/psqs.sls:359:0:balance
  2.53      0.35      0.35  &lt;
  2.24      0.31      0.31  %after-gc-thunk
...
---
Sample count: 671
Total time: 13.97066953 seconds (4.1994665 seconds in GC)
</pre>

<p>
I cannot fix <code>struct-ref</code>, so I finally consider this task done.
Though it is now 30 months after my first try.
</p>
</div>
</div>
]]></description>
</item>
<item>
<title>Day 16, Puzzle 1: Read Elf Transmission</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-16-puzzle-1</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-16-puzzle-1</guid>
<pubDate>Thu, 03 Oct 2024 19:13:00 +0200</pubDate>

<description><![CDATA[<p>
After diving into the deep end, we get back to fundamentals: parsing
bitstreams represented in hexadecimal.
</p>

<p>
Example packets:
</p>

<div class="org-src-container">
<pre class="src src-scheme"><code>D2FE28
EE00D40C823060
8A004A801A8002F478
620080001611562C8802118E34
C0015000016115A2E0802F182340
A0016C880162017C3686B18A3D4780
</code></pre>
</div>

<p>
Let’s do that test-driven. Start with the test-setup:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">srfi</span> :1 lists
<span style="color: #0000ff;">         srfi</span> :26 cut
<span style="color: #0000ff;">         srfi</span> :60 integers-as-bits
<span style="color: #0000ff;">         srfi</span> :64 tests
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :11) let-values
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> match) match-let <span style="color: #b22222;">;; </span><span style="color: #b22222;">pattern matching</span>

<span style="color: #b22222;">;; </span><span style="color: #b22222;">implementations that will be tested</span>
<span style="color: #0000ff;">{{{d16-parse-hexadecimal}}}</span>
<span style="color: #0000ff;">{{{d16-parse-literal-packets}}}</span>
<span style="color: #0000ff;">{{{d16-parse-operator-packets}}}</span>

<span style="color: #0000ff;">test-begin</span> <span style="color: #8b2252;">"elf-messages"</span>

<span style="color: #0000ff;">{{{d16-parse-hexadecimal--tests}}}</span>
<span style="color: #0000ff;">{{{d16-parse-literal-packets--tests}}}</span>
<span style="color: #0000ff;">{{{d16-parse-operator-packets--tests}}}</span>

<span style="color: #0000ff;">{{{d16-input-data-test}}}</span>

<span style="color: #0000ff;">test-end</span>

</code></pre>
</div>

<p>
See test results:
</p>

<div class="org-src-container">
<pre class="src src-bash"><code>cat <span style="color: #8b2252;">"elf-messages.log"</span>
</code></pre>
</div>

<p>
First we need to parse Hexadecimal into binary:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">snippet: {{{d16-parse-hexadecimal--tests}}}</span>
<span style="color: #0000ff;">test-equal</span> #*110100101111111000101000
<span style="color: #0000ff;">  hexadecimal-&gt;bits</span> <span style="color: #8b2252;">"D2FE28"</span>
<span style="color: #0000ff;">test-equal</span> 
<span style="color: #a020f0;">  . </span>#*0000000100100011010001010110011110001001101010111100110111101111
<span style="color: #0000ff;">  hexadecimal-&gt;bits</span> <span style="color: #8b2252;">"0123456789abcdef"</span>
</code></pre>
</div>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">snippet: {{{d16-parse-hexadecimal}}}</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">hexadecimal-&gt;bits</span> hex
<span style="color: #a020f0;">  . </span><span style="color: #8b2252;">"Turn hexadecimal string into a bitvector"</span>
<span style="color: #0000ff;">  apply</span> bitvector <span style="color: #b22222;">;; </span><span style="color: #b22222;">turn bits into efficient bitarray</span>
<span style="color: #0000ff;">    append-map</span> (<span style="color: #0000ff;">cut</span> integer-&gt;list &lt;&gt; <span style="color: #008b8b;">4</span>) <span style="color: #b22222;">;; </span><span style="color: #b22222;">represent as bits</span>
<span style="color: #0000ff;">      map</span> (<span style="color: #0000ff;">cut</span> string-&gt;number &lt;&gt; <span style="color: #008b8b;">16</span>) <span style="color: #b22222;">;; </span><span style="color: #b22222;">parse as hexadecimal</span>
<span style="color: #0000ff;">        map</span> string <span style="color: #b22222;">;; </span><span style="color: #b22222;">turn back to one-element strings</span>
<span style="color: #0000ff;">          string-&gt;list</span> hex <span style="color: #b22222;">;; </span><span style="color: #b22222;">split into characters</span>
</code></pre>
</div>

<p>
Then we parse literal packets (direct data):
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">snippet: {{{d16-parse-literal-packets--tests}}}</span>
<span style="color: #0000ff;">test-equal</span> '(<span style="color: #008b8b;">6</span><span style="color: #a020f0;"> . </span><span style="color: #008b8b;">4</span>)
<span style="color: #0000ff;">  identify-packet</span> #*110100101111111000101000
<span style="color: #0000ff;">test-equal</span> <span style="color: #008b8b;">2021</span>
<span style="color: #0000ff;">  literal-value-packet-data</span> #*110100101111111000101000
</code></pre>
</div>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">snippet: {{{d16-parse-literal-packets}}}</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">bitvector-&gt;integer</span> vec
<span style="color: #0000ff;">    list-&gt;integer</span>
<span style="color: #0000ff;">      bitvector-&gt;list</span> vec

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">identify-packet</span> packet
<span style="color: #a020f0;">  . </span><span style="color: #8b2252;">"Return (version . type) for the PACKET."</span>
  <span style="color: #483d8b;">define</span> version<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">bitvector-&gt;integer</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">bitvector-copy</span> packet <span style="color: #008b8b;">0</span> <span style="color: #008b8b;">3</span>
  <span style="color: #483d8b;">define</span> type<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">bitvector-&gt;integer</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">bitvector-copy</span> packet <span style="color: #008b8b;">3</span> <span style="color: #008b8b;">6</span>
<span style="color: #0000ff;">  cons</span> version type

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">bitvectors-&gt;integer</span><span style="color: #a020f0;"> . </span>packets
<span style="color: #a020f0;">  . </span><span style="color: #8b2252;">"Flatten subvectors and re-interpret the bits as integer"</span>
<span style="color: #0000ff;">  list-&gt;integer</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> append<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> bitvector-&gt;list packets

<span style="color: #0000ff;">define*</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">literal-value-packet-data</span> packet #:key (<span style="color: #0000ff;">start</span> <span style="color: #008b8b;">6</span>)
<span style="color: #a020f0;">  . </span><span style="color: #8b2252;">"Return values: data as integer and index after the last bit."</span>
  <span style="color: #483d8b;">let</span> loop<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">(nibbles</span> <span style="color: #008b8b;">'()</span>) (<span style="color: #0000ff;">index</span> start)
    <span style="color: #483d8b;">define</span> nibble<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">bitvector-copy</span> packet {index + 1} {index + 5}
    <span style="color: #483d8b;">define</span> value<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cons</span> nibble nibbles
    <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #483d8b;">not</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">bitvector-bit-set?</span> packet index
<span style="color: #0000ff;">       values</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> bitvectors-&gt;integer<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">reverse!</span> value
<span style="color: #0000ff;">              +</span> index <span style="color: #008b8b;">5</span>
<span style="color: #0000ff;">       loop</span> value {index + 5}
</code></pre>
</div>

<p>
Now we parse operator packets (packets containing packets) and extract versions:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">snippet: {{{d16-parse-operator-packets--tests}}}</span>
<span style="color: #b22222;">;; </span><span style="color: #b22222;">packet types other than 4 are detected</span>
<span style="color: #0000ff;">test-equal</span> '(<span style="color: #008b8b;">1</span><span style="color: #a020f0;"> . </span><span style="color: #008b8b;">6</span>) <span style="color: #b22222;">;; </span><span style="color: #b22222;">6 means operator type</span>
<span style="color: #0000ff;">  identify-packet</span>
<span style="color: #0000ff;">    hexadecimal-&gt;bits</span> <span style="color: #8b2252;">"38006F45291200"</span>
<span style="color: #b22222;">;; </span><span style="color: #b22222;">operator length type bitcount and packet number are detected</span>
<span style="color: #0000ff;">test-equal</span> <span style="color: #008b8b;">15</span>
<span style="color: #0000ff;">  operator-length-bitlength</span>
<span style="color: #0000ff;">    hexadecimal-&gt;bits</span> <span style="color: #8b2252;">"38006F45291200"</span>
<span style="color: #0000ff;">test-equal</span> <span style="color: #008b8b;">11</span>
<span style="color: #0000ff;">  operator-length-bitlength</span>
<span style="color: #0000ff;">    hexadecimal-&gt;bits</span> <span style="color: #8b2252;">"EE00D40C823060"</span>
<span style="color: #b22222;">;; </span><span style="color: #b22222;">parses packet versions</span>
<span style="color: #0000ff;">test-equal</span> '(<span style="color: #008b8b;">1</span> <span style="color: #008b8b;">6</span> <span style="color: #008b8b;">2</span>)
<span style="color: #0000ff;">  extract-packet-versions</span>
<span style="color: #0000ff;">    hexadecimal-&gt;bits</span> <span style="color: #8b2252;">"38006F45291200"</span>
<span style="color: #0000ff;">test-equal</span> '(<span style="color: #008b8b;">7</span> <span style="color: #008b8b;">2</span> <span style="color: #008b8b;">4</span> <span style="color: #008b8b;">1</span>)
<span style="color: #0000ff;">  extract-packet-versions</span>
<span style="color: #0000ff;">    hexadecimal-&gt;bits</span> <span style="color: #8b2252;">"EE00D40C823060"</span>
<span style="color: #b22222;">;; </span><span style="color: #b22222;">gives correct version sums</span>
<span style="color: #0000ff;">test-equal</span> <span style="color: #008b8b;">16</span>
<span style="color: #0000ff;">  apply</span> + <span style="color: #b22222;">;; </span><span style="color: #b22222;">apply + calculates the sum of the values in a list</span>
<span style="color: #0000ff;">    extract-packet-versions</span>
<span style="color: #0000ff;">      hexadecimal-&gt;bits</span> <span style="color: #8b2252;">"8A004A801A8002F478"</span>
<span style="color: #0000ff;">test-equal</span> <span style="color: #008b8b;">12</span>
<span style="color: #0000ff;">  apply</span> +
<span style="color: #0000ff;">    extract-packet-versions</span>
<span style="color: #0000ff;">      hexadecimal-&gt;bits</span> <span style="color: #8b2252;">"620080001611562C8802118E34"</span>
<span style="color: #0000ff;">test-equal</span> <span style="color: #008b8b;">23</span>
<span style="color: #0000ff;">  apply</span> +
<span style="color: #0000ff;">    extract-packet-versions</span>
<span style="color: #0000ff;">      hexadecimal-&gt;bits</span> <span style="color: #8b2252;">"C0015000016115A2E0802F182340"</span>
<span style="color: #0000ff;">test-equal</span> <span style="color: #008b8b;">31</span>
<span style="color: #0000ff;">  apply</span> +
<span style="color: #0000ff;">    extract-packet-versions</span>
<span style="color: #0000ff;">      hexadecimal-&gt;bits</span> <span style="color: #8b2252;">"A0016C880162017C3686B18A3D4780"</span>
</code></pre>
</div>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">snippet: {{{d16-parse-operator-packets}}}</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">operator-length-bitlength</span> packet
  <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">bitvector-bit-set?</span> packet <span style="color: #008b8b;">6</span>
<span style="color: #a020f0;">     . </span><span style="color: #008b8b;">11</span> <span style="color: #008b8b;">15</span>

<span style="color: #0000ff;">define*</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">extract-packet-versions</span> packet #:optional max-packets
<span style="color: #a020f0;">  . </span><span style="color: #8b2252;">"Extract the version numbers of all packets as flat list."</span>
  <span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">done</span> start-index
<span style="color: #a020f0;">    . </span><span style="color: #8b2252;">"check whether enough bits remain for the minimum packet"</span>
    <span style="color: #483d8b;">define</span> min-bits {6 + 5} <span style="color: #b22222;">;; </span><span style="color: #b22222;">header plus one literal data nibble</span>
<span style="color: #0000ff;">    &gt;</span> {start-index + min-bits}<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">bitvector-length</span> packet
<span style="color: #0000ff;">  match-let</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> (<span style="color: #0000ff;">version</span><span style="color: #a020f0;"> . </span>type)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">identify-packet</span> packet
    <span style="color: #b22222;">;; </span><span style="color: #b22222;">no more packets to parse or not enough bits for a packet</span>
    <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #483d8b;">or</span> (<span style="color: #0000ff;">and=&gt;</span> max-packets zero?)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">done</span> <span style="color: #008b8b;">0</span>
<span style="color: #a020f0;">       . </span><span style="color: #008b8b;">'()</span> <span style="color: #b22222;">;; </span><span style="color: #b22222;">rest of the packet is only padding</span>
<span style="color: #0000ff;">       cons</span> version
<span style="color: #0000ff;">        cond</span>
<span style="color: #a020f0;">          : </span><span style="color: #0000ff;">equal?</span> <span style="color: #008b8b;">4</span> type <span style="color: #b22222;">;; </span><span style="color: #b22222;">literal value</span>
<span style="color: #0000ff;">            let-values</span>
<span style="color: #a020f0;">              : </span><span style="color: #0000ff;">(data</span> after-end)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">literal-value-packet-data</span> packet
              <span style="color: #483d8b;">if</span> (<span style="color: #0000ff;">done</span> after-end) <span style="color: #008b8b;">'()</span>
<span style="color: #0000ff;">                extract-packet-versions</span>
<span style="color: #0000ff;">                  bitvector-copy</span> packet after-end 
<span style="color: #0000ff;">          else</span> <span style="color: #b22222;">;; </span><span style="color: #b22222;">operator packet that can have sub-packets</span>
             <span style="color: #483d8b;">let*</span>
<span style="color: #a020f0;">               : </span><span style="color: #0000ff;">len-bits</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">operator-length-bitlength</span> packet
<span style="color: #0000ff;">                 data-start</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">+</span> <span style="color: #008b8b;">6</span> <span style="color: #008b8b;">1</span> len-bits
<span style="color: #0000ff;">                 subvec</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">bitvector-copy</span> packet <span style="color: #008b8b;">7</span> data-start
<span style="color: #0000ff;">                 len</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">list-&gt;integer</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">bitvector-&gt;list</span> subvec
               <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">=</span> <span style="color: #008b8b;">15</span> len-bits
                 <span style="color: #b22222;">;; </span><span style="color: #b22222;">fixed length, arbitrary number of packets</span>
<span style="color: #0000ff;">                 append</span>
                     <span style="color: #b22222;">;; </span><span style="color: #b22222;">extract packets from packet-body</span>
<span style="color: #0000ff;">                     extract-packet-versions</span>
<span style="color: #0000ff;">                       bitvector-copy</span> packet data-start
<span style="color: #0000ff;">                         +</span> data-start len
                     <span style="color: #b22222;">;; </span><span style="color: #b22222;">extract further packets after the packet body</span>
                     <span style="color: #483d8b;">if</span>
                       <span style="color: #483d8b;">or</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">equal?</span> max-packets <span style="color: #008b8b;">1</span>
<span style="color: #0000ff;">                            done</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">+</span> data-start len
<span style="color: #a020f0;">                       . </span><span style="color: #008b8b;">'()</span>
<span style="color: #0000ff;">                       extract-packet-versions</span>
<span style="color: #0000ff;">                         bitvector-copy</span> packet<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">+</span> data-start len
<span style="color: #0000ff;">                         and=&gt;</span> max-packets 1-
                 <span style="color: #b22222;">;; </span><span style="color: #b22222;">unknown length, fixed num of packets: keep parsing</span>
<span style="color: #0000ff;">                 extract-packet-versions</span>
<span style="color: #0000ff;">                   bitvector-copy</span> packet data-start
<span style="color: #a020f0;">                   . </span>len
</code></pre>
</div>

<p>
Finally we check whether the actual input is parsed correctly:
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">snippet: {{{d16-input-data-test}}}</span>
<span style="color: #b22222;">;; </span><span style="color: #b22222;">my input gives the correct version sum</span>
<span style="color: #0000ff;">test-equal</span> <span style="color: #008b8b;">993</span>
<span style="color: #0000ff;">  apply</span> +
<span style="color: #0000ff;">    extract-packet-versions</span>
<span style="color: #0000ff;">      hexadecimal-&gt;bits</span>
<span style="color: #0000ff;">        string-append</span> <span style="color: #8b2252;">"420D5A802122FD25C8CD7CC010B00564D0E4B76C7D5A"</span>
<span style="color: #a020f0;">          . </span><span style="color: #8b2252;">"59C8C014E007325F116C958F2C7D31EB4EDF90A9803B2EB5340924"</span>
<span style="color: #a020f0;">          . </span><span style="color: #8b2252;">"CA002761803317E2B4793006E28C2286440087C5682312D0024B9E"</span>
<span style="color: #a020f0;">          . </span><span style="color: #8b2252;">"F464DF37EFA0CD031802FA00B4B7ED2D6BD2109485E3F3791FDEB3"</span>
<span style="color: #a020f0;">          . </span><span style="color: #8b2252;">"AF0D8802A899E49370012A926A9F8193801531C84F5F573004F803"</span>
<span style="color: #a020f0;">          . </span><span style="color: #8b2252;">"571006A2C46B8280008645C8B91924AD3753002E512400CC170038"</span>
<span style="color: #a020f0;">          . </span><span style="color: #8b2252;">"400A002BCD80A445002440082021DD807C0201C510066670035C00"</span>
<span style="color: #a020f0;">          . </span><span style="color: #8b2252;">"940125D803E170030400B7003C0018660034E6F180120104257588"</span>
<span style="color: #a020f0;">          . </span><span style="color: #8b2252;">"0A5004D9372A520E735C876FD2C3008274D24CDE614A68626D9480"</span>
<span style="color: #a020f0;">          . </span><span style="color: #8b2252;">"4D4929693F003531006A1A47C85000084C4586B10D802F5977E88D"</span>
<span style="color: #a020f0;">          . </span><span style="color: #8b2252;">"2DD2898D6F17A614CC0109E9CE97D02D006EC00086C64859174001"</span>
<span style="color: #a020f0;">          . </span><span style="color: #8b2252;">"0C8AF14E0E180253673400AA48D15E468A2000ADCCED1A174218D6"</span>
<span style="color: #a020f0;">          . </span><span style="color: #8b2252;">"C017DCFAA4EB2C8C5FA7F21D3F9152012F6C01797FF3B4AE38C32F"</span>
<span style="color: #a020f0;">          . </span><span style="color: #8b2252;">"FE7695C719A6AB5E25080250EE7BB7FEF72E13980553CE932EB26C"</span>
<span style="color: #a020f0;">          . </span><span style="color: #8b2252;">"72A2D26372D69759CC014F005E7E9F4E9FA7D3653FCC879803E200"</span>
<span style="color: #a020f0;">          . </span><span style="color: #8b2252;">"CC678470EC0010E82B11E34080330D211C663004F0010191179117"</span>
<span style="color: #a020f0;">          . </span><span style="color: #8b2252;">"9296E7F869F9C017998EF11A1BCA52989F5EA778866008D8023255"</span>
<span style="color: #a020f0;">          . </span><span style="color: #8b2252;">"DFBB7BD2A552B65A98ECFEC51D540209DFF2FF2B9C1B9FE5D6A469"</span>
<span style="color: #a020f0;">          . </span><span style="color: #8b2252;">"F81590079160094CD73D85FD2699C5C9DCF21F0700094A1AC9EDA6"</span>
<span style="color: #a020f0;">          . </span><span style="color: #8b2252;">"4AE3D37D34200B7B401596D678A73AFB2D0B1B88057230A42B2BD8"</span>
<span style="color: #a020f0;">          . </span><span style="color: #8b2252;">"8E7F9F0C94F1ECB7B0DD393489182F9802D3F875C00DC40010F891"</span>
<span style="color: #a020f0;">          . </span><span style="color: #8b2252;">"1C61F8002111BA1FC2E400BEA5AA0334F9359EA741892D81100B83"</span>
<span style="color: #a020f0;">          . </span><span style="color: #8b2252;">"337BD2DDB4E43B401A800021F19A09C1F1006229C3F8726009E002"</span>
<span style="color: #a020f0;">          . </span><span style="color: #8b2252;">"A12D71B96B8E49BB180273AA722468002CC7B818C01B04F77B39EF"</span>
<span style="color: #a020f0;">          . </span><span style="color: #8b2252;">"DF53973D95ADB5CD921802980199CF4ADAA7B67B3D9ACFBEC4F82D"</span>
<span style="color: #a020f0;">          . </span><span style="color: #8b2252;">"19A4F75DE78002007CD6D1A24455200A0E5C47801559BF58665D80"</span>

</code></pre>
</div>
]]></description>
</item>
<item>
<title>Day 16, Puzzle 2: Math for Elves</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-16-puzzle-2</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-16-puzzle-2</guid>
<pubDate>Sat, 12 Jul 2025 00:00:00 +0200</pubDate>

<description><![CDATA[<p>
Operator packets are math.
</p>

<p>
Let’s combine the parts from day one into one unified piece of code.
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">srfi</span> :1 lists
<span style="color: #0000ff;">         srfi</span> :26 cut
<span style="color: #0000ff;">         srfi</span> :60 integers-as-bits
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :11) let-values
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">ice-9</span> match) match-let

<span style="color: #b22222;">;; </span><span style="color: #b22222;">map packet IDs to operator procedures</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">comp</span> op
  <span style="color: #483d8b;">define</span> proc
<span style="color: #0000ff;">    &#955;</span> (<span style="color: #a020f0;">. </span>x)<span style="color: #a020f0;"> : </span><span style="color: #483d8b;">if</span> (<span style="color: #0000ff;">apply</span> op x) <span style="color: #008b8b;">1</span> <span style="color: #008b8b;">0</span>
  <span style="color: #b22222;">;; </span><span style="color: #b22222;">preserve the name for easier debugging</span>
<span style="color: #0000ff;">  set-procedure-property!</span> proc<span style="color: #008b8b;"> 'name</span>
<span style="color: #0000ff;">    procedure-name</span> op
<span style="color: #a020f0;">  . </span>proc

<span style="color: #483d8b;">define</span> id-operator-map
<span style="color: #0000ff;">  `</span>
<span style="color: #0000ff;">    0</span><span style="color: #a020f0;"> . </span>,+
<span style="color: #0000ff;">    1</span><span style="color: #a020f0;"> . </span>,*
<span style="color: #0000ff;">    2</span><span style="color: #a020f0;"> . </span>,min
<span style="color: #0000ff;">    3</span><span style="color: #a020f0;"> . </span>,max
<span style="color: #0000ff;">    4</span><span style="color: #a020f0;"> . </span><span style="color: #008b8b;">#f</span> <span style="color: #b22222;">;; </span><span style="color: #b22222;">data</span>
<span style="color: #0000ff;">    5</span><span style="color: #a020f0;"> . </span>,<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">comp</span> &gt;
<span style="color: #0000ff;">    6</span><span style="color: #a020f0;"> . </span>,<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">comp</span> &lt;
<span style="color: #0000ff;">    7</span><span style="color: #a020f0;"> . </span>,<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">comp</span> equal?

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">id-&gt;operator</span> id
<span style="color: #0000ff;"> and=&gt;</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">assoc</span> id id-operator-map
<span style="color: #a020f0;">       . </span>cdr

<span style="color: #b22222;">;; </span><span style="color: #b22222;">unchanged tools</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">hexadecimal-&gt;bits</span> hex
<span style="color: #a020f0;">  . </span><span style="color: #8b2252;">"Turn hexadecimal string into a bitvector"</span>
<span style="color: #0000ff;">  apply</span> bitvector <span style="color: #b22222;">;; </span><span style="color: #b22222;">turn bits into efficient bitarray</span>
<span style="color: #0000ff;">    append-map</span> (<span style="color: #0000ff;">cut</span> integer-&gt;list &lt;&gt; <span style="color: #008b8b;">4</span>) <span style="color: #b22222;">;; </span><span style="color: #b22222;">represent as bits</span>
<span style="color: #0000ff;">      map</span> (<span style="color: #0000ff;">cut</span> string-&gt;number &lt;&gt; <span style="color: #008b8b;">16</span>) <span style="color: #b22222;">;; </span><span style="color: #b22222;">parse as hexadecimal</span>
<span style="color: #0000ff;">        map</span> string <span style="color: #b22222;">;; </span><span style="color: #b22222;">turn back to one-element strings</span>
<span style="color: #0000ff;">          string-&gt;list</span> hex <span style="color: #b22222;">;; </span><span style="color: #b22222;">split into characters</span>

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">bitvector-&gt;integer</span> vec
<span style="color: #0000ff;">    list-&gt;integer</span>
<span style="color: #0000ff;">      bitvector-&gt;list</span> vec

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">identify-packet</span> packet
<span style="color: #a020f0;">  . </span><span style="color: #8b2252;">"Return (version . type) for the PACKET."</span>
  <span style="color: #483d8b;">define</span> version<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">bitvector-&gt;integer</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">bitvector-copy</span> packet <span style="color: #008b8b;">0</span> <span style="color: #008b8b;">3</span>
  <span style="color: #483d8b;">define</span> type<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">bitvector-&gt;integer</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">bitvector-copy</span> packet <span style="color: #008b8b;">3</span> <span style="color: #008b8b;">6</span>
<span style="color: #0000ff;">  cons</span> version type

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">bitvectors-&gt;integer</span><span style="color: #a020f0;"> . </span>packets
<span style="color: #a020f0;">  . </span><span style="color: #8b2252;">"Flatten subvectors and re-interpret the bits as integer"</span>
<span style="color: #0000ff;">  list-&gt;integer</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> append<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> bitvector-&gt;list packets

<span style="color: #0000ff;">define*</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">literal-value-packet-data</span> packet #:key (<span style="color: #0000ff;">start</span> <span style="color: #008b8b;">6</span>)
<span style="color: #a020f0;">  . </span><span style="color: #8b2252;">"Return values: data as integer and index after the last bit."</span>
  <span style="color: #483d8b;">let</span> loop<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">(nibbles</span> <span style="color: #008b8b;">'()</span>) (<span style="color: #0000ff;">index</span> start)
    <span style="color: #483d8b;">define</span> nibble<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">bitvector-copy</span> packet {index + 1} {index + 5}
    <span style="color: #483d8b;">define</span> value<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cons</span> nibble nibbles
    <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #483d8b;">not</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">bitvector-bit-set?</span> packet index
<span style="color: #0000ff;">       values</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> bitvectors-&gt;integer<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">reverse!</span> value
<span style="color: #0000ff;">              +</span> index <span style="color: #008b8b;">5</span>
<span style="color: #0000ff;">       loop</span> value {index + 5}

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">operator-length-bitlength</span> packet
  <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">bitvector-bit-set?</span> packet <span style="color: #008b8b;">6</span>
<span style="color: #a020f0;">     . </span><span style="color: #008b8b;">11</span> <span style="color: #008b8b;">15</span>

<span style="color: #b22222;">;; </span><span style="color: #b22222;">adjusted parsing</span>
<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">operator-packet/fixed-len</span> packet op data-start len
<span style="color: #a020f0;">    . </span><span style="color: #8b2252;">"parse operator packet: fixed length, arbitrary packet-count."</span>
    <span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">after-the-end?</span> index len
        <span style="color: #483d8b;">define</span> minimal-packet {len + <span style="color: #008b8b;">6</span> + 5}
<span style="color: #a020f0;">        . </span>{index &gt; minimal-packet}
    <span style="color: #483d8b;">let</span> loop
<span style="color: #a020f0;">      : </span><span style="color: #0000ff;">next-packet</span> data-start
<span style="color: #0000ff;">        packets</span> <span style="color: #008b8b;">'()</span>
      <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">after-the-end?</span> next-packet len
         <span style="color: #b22222;">;; </span><span style="color: #b22222;">return the result and the end of the body</span>
<span style="color: #0000ff;">         values</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> op<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">reverse</span> packets
<span style="color: #0000ff;">                +</span> data-start len <span style="color: #b22222;">;; </span><span style="color: #b22222;">end of body</span>
         <span style="color: #b22222;">;; </span><span style="color: #b22222;">extract packets from the packet-body</span>
<span style="color: #0000ff;">         let-values</span>
<span style="color: #a020f0;">           :</span>
<span style="color: #a020f0;">             : </span><span style="color: #0000ff;">data</span> after-end
<span style="color: #0000ff;">               calculate-result</span>
<span style="color: #0000ff;">                 bitvector-copy</span> packet next-packet
<span style="color: #0000ff;">           loop</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">+</span> next-packet after-end
<span style="color: #0000ff;">                cons</span> data packets

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">operator-packet/fixed-num</span> packet op data-start len
<span style="color: #a020f0;">    . </span><span style="color: #8b2252;">"parse operator packet: unknown length, fixed packets-count."</span>
    <span style="color: #483d8b;">let</span> loop
<span style="color: #a020f0;">      : </span><span style="color: #0000ff;">next-packet</span> data-start
<span style="color: #0000ff;">        packets</span> <span style="color: #008b8b;">'()</span>
<span style="color: #0000ff;">        remaining</span> len
      <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">zero?</span> remaining
<span style="color: #0000ff;">         values</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">apply</span> op<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">reverse</span> packets
<span style="color: #a020f0;">                . </span>next-packet
<span style="color: #0000ff;">         let-values</span>
<span style="color: #a020f0;">           :</span>
<span style="color: #a020f0;">             : </span><span style="color: #0000ff;">data</span> after-end
<span style="color: #0000ff;">               calculate-result</span>
<span style="color: #0000ff;">                 bitvector-copy</span> packet next-packet
<span style="color: #0000ff;">           loop</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">+</span> next-packet after-end
<span style="color: #0000ff;">                cons</span> data packets
<span style="color: #0000ff;">                1-</span> remaining

<span style="color: #0000ff;">define*</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">calculate-result</span> packet
<span style="color: #a020f0;">  . </span><span style="color: #8b2252;">"Extract the data of literal packets and apply operations."</span>
<span style="color: #0000ff;">  match-let</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">:</span> (<span style="color: #0000ff;">version</span><span style="color: #a020f0;"> . </span>type)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">identify-packet</span> packet
    <span style="color: #483d8b;">define</span> op<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">id-&gt;operator</span> type
    <span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">extract-len</span> packet data-start
<span style="color: #a020f0;">        . </span><span style="color: #8b2252;">"extract the length data of the packet as integer."</span>
        <span style="color: #483d8b;">define</span> vec<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">bitvector-copy</span> packet <span style="color: #008b8b;">7</span> data-start
<span style="color: #0000ff;">        list-&gt;integer</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">bitvector-&gt;list</span> vec
    <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #483d8b;">not</span> op
<span style="color: #0000ff;">       literal-value-packet-data</span> packet
       <span style="color: #483d8b;">let*</span> <span style="color: #b22222;">;; </span><span style="color: #b22222;">operator packet that can have sub-packets</span>
<span style="color: #a020f0;">         : </span><span style="color: #0000ff;">len-bits</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">operator-length-bitlength</span> packet
<span style="color: #0000ff;">           data-start</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">+</span> <span style="color: #008b8b;">6</span> <span style="color: #008b8b;">1</span> len-bits
<span style="color: #0000ff;">           len</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">extract-len</span> packet data-start
<span style="color: #0000ff;">           extractor</span>
             <span style="color: #483d8b;">if</span> {len-bits = 15}
<span style="color: #a020f0;">               . </span>operator-packet/fixed-len
<span style="color: #a020f0;">               . </span>operator-packet/fixed-num
<span style="color: #0000ff;">         extractor</span> packet op data-start len

<span style="color: #0000ff;">equal?</span> '(<span style="color: #008b8b;">3</span> <span style="color: #008b8b;">54</span> <span style="color: #008b8b;">7</span> <span style="color: #008b8b;">9</span> <span style="color: #008b8b;">1</span> <span style="color: #008b8b;">0</span> <span style="color: #008b8b;">0</span> <span style="color: #008b8b;">1</span>)
<span style="color: #0000ff;">  map</span> calculate-result
<span style="color: #0000ff;">    map</span> hexadecimal-&gt;bits<span style="color: #008b8b;"> '(</span>
      <span style="color: #8b2252;">"C200B40A82"</span> <span style="color: #b22222;">;; </span><span style="color: #b22222;">1+2 =&gt; 3</span>
      <span style="color: #8b2252;">"04005AC33890"</span> <span style="color: #b22222;">;; </span><span style="color: #b22222;">6*9 =&gt; 54</span>
      <span style="color: #8b2252;">"880086C3E88112"</span> <span style="color: #b22222;">;; </span><span style="color: #b22222;">min 7 8 9 =&gt; 7</span>
      <span style="color: #8b2252;">"CE00C43D881120"</span> <span style="color: #b22222;">;; </span><span style="color: #b22222;">max 7 8 9 =&gt; 9</span>
      <span style="color: #8b2252;">"D8005AC2A8F0"</span> <span style="color: #b22222;">;; </span><span style="color: #b22222;">&lt; 5 15 =&gt; 1</span>
      <span style="color: #8b2252;">"F600BC2D8F"</span> <span style="color: #b22222;">;; </span><span style="color: #b22222;">&gt; 5 15 =&gt; 0</span>
      <span style="color: #8b2252;">"9C005AC2F8F0"</span> <span style="color: #b22222;">;; </span><span style="color: #b22222;">= 5 15 =&gt; 0 </span>
      <span style="color: #8b2252;">"9C0141080250320F1802104A08"</span> <span style="color: #b22222;">;; </span><span style="color: #b22222;">1+3 = 2*2 =&gt; 1</span>
<span style="color: #0000ff;">    )</span>
</code></pre>
</div>

<p>
This is not very efficient, because it copies bitvectors around all
the time. More efficient would be to have a view on the bitvectors,
since it’s readonly. But at this point I’m happy with the result.
</p>
]]></description>
</item>
<item>
<title>Day 17, Puzzle 1: Aim for the Area</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-17-puzzle-1</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-17-puzzle-1</guid>
<pubDate>Sat, 12 Jul 2025 00:00:00 +0200</pubDate>

<description><![CDATA[<p>
Calculate discrete trajectories to reach as high as possible while
touching the target area.
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #0000ff;">import</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">only</span> (<span style="color: #0000ff;">srfi</span> :9) define-record-type
<span style="color: #0000ff;">         only</span> (<span style="color: #0000ff;">srfi</span> :26) cut

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">parse-input</span> s
<span style="color: #a020f0;">  . </span><span style="color: #8b2252;">"parse an input definition like</span>

<span style="color: #8b2252;">target area: x=20..30, y=-10..-5</span>

<span style="color: #8b2252;">Returns x-min x-max y-min y-max</span>
<span style="color: #8b2252;">"</span>
<span style="color: #0000ff;">  map</span> string-&gt;number
<span style="color: #0000ff;">    string-tokenize</span> s
<span style="color: #0000ff;">      char-set-adjoin</span>
<span style="color: #0000ff;">        char-set-intersection</span> char-set:ascii char-set:digit
<span style="color: #a020f0;">        . </span>#\-

<span style="color: #0000ff;">define-record-type</span> &lt;particle&gt;
<span style="color: #0000ff;">  make-particle</span> x y dx dy init
<span style="color: #a020f0;">  . </span>particle?
<span style="color: #0000ff;">  x</span> p-x
<span style="color: #0000ff;">  y</span> p-y
<span style="color: #0000ff;">  dx</span> p-dx
<span style="color: #0000ff;">  dy</span> p-dy
<span style="color: #0000ff;">  init</span> p-init <span style="color: #b22222;">;; </span><span style="color: #b22222;">initial values for tracing</span>

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">step</span> p
  <span style="color: #483d8b;">define</span> dx<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">p-dx</span> p
<span style="color: #0000ff;">  make-particle</span>
<span style="color: #0000ff;">    +</span> (<span style="color: #0000ff;">p-x</span> p) (<span style="color: #0000ff;">p-dx</span> p)
<span style="color: #0000ff;">    +</span> (<span style="color: #0000ff;">p-y</span> p) (<span style="color: #0000ff;">p-dy</span> p)
    <span style="color: #483d8b;">if</span> {dx &lt; 0} {dx + 1}<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">max</span> <span style="color: #008b8b;">0</span> {dx - 1}
<span style="color: #0000ff;">    -</span> (<span style="color: #0000ff;">p-dy</span> p) <span style="color: #008b8b;">1</span>
<span style="color: #0000ff;">    p-init</span> p

<span style="color: #0000ff;">define*</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">calculate-trajectory</span> particle x-min x-max y-min
  <span style="color: #483d8b;">let</span> loop<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">(points</span> (<span style="color: #0000ff;">list</span> particle))
    <span style="color: #483d8b;">define</span> p<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">car</span> points
    <span style="color: #483d8b;">define</span> x<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">p-x</span> p
    <span style="color: #483d8b;">define</span> y<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">p-y</span> p
    <span style="color: #483d8b;">define</span> dx<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">p-dx</span> p
    <span style="color: #483d8b;">if</span><span style="color: #a020f0;"> : </span><span style="color: #483d8b;">or</span> {y &lt; y-min} {x &gt; x-max}<span style="color: #a020f0;"> : </span><span style="color: #483d8b;">and</span> {dx = 0} {x &lt; x-min}
<span style="color: #0000ff;">       reverse</span> points
<span style="color: #0000ff;">       loop</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cons</span> (<span style="color: #0000ff;">step</span> p) points

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">touches-area?</span> trajectory x-min x-max y-min y-max
  <span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">in-target?</span> particle
    <span style="color: #483d8b;">define</span> x<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">p-x</span> particle
    <span style="color: #483d8b;">define</span> y<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">p-y</span> particle
    <span style="color: #483d8b;">and</span> {x &gt;= x-min} {x &lt;= x-max} {y &gt;= y-min} {y &lt;= y-max}
  <span style="color: #483d8b;">not</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">null?</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">filter</span> in-target? trajectory

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">max-y</span> trajectory
<span style="color: #0000ff;">  apply</span> max<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> p-y trajectory


<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">velocity-parameter-range</span> x-min x-max y-min
  <span style="color: #483d8b;">when</span> {y-min &gt;= 0}
<span style="color: #0000ff;">    throw</span><span style="color: #008b8b;"> 'arguments-invalid-must-be-smaller-0</span> y-min
  <span style="color: #b22222;">;; </span><span style="color: #b22222;">after coming down, dy is exactly -dy, so it must be at most</span>
  <span style="color: #b22222;">;; </span><span style="color: #b22222;">(abs y-min), else the first step below 0 already overshoots.</span>
  <span style="color: #483d8b;">define</span> dy-values
<span style="color: #0000ff;">     iota</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">1+</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">*</span> <span style="color: #008b8b;">2</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">abs</span> y-min <span style="color: #b22222;">;; </span><span style="color: #b22222;">number of steps</span>
<span style="color: #a020f0;">       . </span>y-min <span style="color: #b22222;">;; </span><span style="color: #b22222;">start: assumption: y-min &lt; 0</span>
<span style="color: #a020f0;">       . </span><span style="color: #008b8b;">1</span>
  <span style="color: #b22222;">;; </span><span style="color: #b22222;">dx must be high enough that dx(dx-1)/2 &gt;= x-min</span>
  <span style="color: #b22222;">;; </span><span style="color: #b22222;">dx(dx+1) &gt;= 2*x-min</span>
  <span style="color: #b22222;">;; </span><span style="color: #b22222;">(dx+1)(dx+1) &gt;= 2*x-min ;; since (x+1)(x+1)&gt;x(x+1)</span>
  <span style="color: #b22222;">;; </span><span style="color: #b22222;">dx + 1 &gt;= sqrt(2*x-min)</span>
  <span style="color: #b22222;">;; </span><span style="color: #b22222;">dx &gt;= sqrt(2*x-min) - 1</span>
  <span style="color: #483d8b;">define</span> dx-start
<span style="color: #0000ff;">    inexact-&gt;exact</span>
<span style="color: #0000ff;">      floor</span>
<span style="color: #0000ff;">        1-</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">sqrt</span> {2 * x-min}
  <span style="color: #b22222;">;; </span><span style="color: #b22222;">dx must be at most x-max, else the first step already overshoots.</span>
  <span style="color: #483d8b;">define</span> dx-values
<span style="color: #0000ff;">    iota</span> (<span style="color: #0000ff;">1+</span> {x-max - dx-start}) dx-start
<span style="color: #0000ff;">  apply</span> append
<span style="color: #0000ff;">    map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;</span> (<span style="color: #0000ff;">x</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">map</span> (<span style="color: #0000ff;">cut</span> cons x &lt;&gt;) dy-values
<span style="color: #a020f0;">      . </span>dx-values

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">velocities-&gt;particle</span> velocities
<span style="color: #0000ff;">  make-particle</span> <span style="color: #008b8b;">0</span> <span style="color: #008b8b;">0</span>
<span style="color: #0000ff;">    car</span> velocities
<span style="color: #0000ff;">    cdr</span> velocities
<span style="color: #a020f0;">    . </span>velocities

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">max-heigth-parameters</span> x-min x-max y-min y-max
<span style="color: #0000ff;">  car</span>
<span style="color: #0000ff;">    sort</span>
<span style="color: #0000ff;">      map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&#955;</span> (<span style="color: #0000ff;">t</span>)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cons</span> (<span style="color: #0000ff;">max-y</span> t) (<span style="color: #0000ff;">p-init</span> (<span style="color: #0000ff;">car</span> t))
<span style="color: #0000ff;">        filter</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cut</span> touches-area? &lt;&gt; x-min x-max y-min y-max
<span style="color: #0000ff;">          map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cut</span> calculate-trajectory &lt;&gt; x-min x-max y-min
<span style="color: #0000ff;">            map</span> velocities-&gt;particle
<span style="color: #0000ff;">              velocity-parameter-range</span> x-min x-max y-min
<span style="color: #0000ff;">      &#955;</span> (<span style="color: #0000ff;">a</span> b)<span style="color: #a020f0;"> : </span><span style="color: #0000ff;">&gt;</span> (<span style="color: #0000ff;">car</span> a) (<span style="color: #0000ff;">car</span> b)

<span style="color: #0000ff;">apply</span> max-heigth-parameters
<span style="color: #0000ff;">  parse-input</span> <span style="color: #8b2252;">"target area: x=20..30, y=-10..-5"</span>
</code></pre>
</div>
]]></description>
</item>
<item>
<title>Day 17, Puzzle 2: All the values</title>
<link>https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-17-puzzle-2</link>
<author>arne@fluss (Dr. Arne Babenhauserheide)</author>
<guid isPermaLink="false">https://www.draketo.de/software/advent-of-wisp-code-2021.html#day-17-puzzle-2</guid>
<pubDate>Sat, 12 Jul 2025 00:00:00 +0200</pubDate>

<description><![CDATA[<p>
The same as before, but count all working initial velocity values.
</p>

<div class="org-src-container">
<pre class="src src-wisp"><code><span style="color: #b22222;">;; </span><span style="color: #b22222;">use all from part 1</span>
{{{d17-part-1}}}

<span style="color: #483d8b;">define</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">count-distinct-parameters</span> x-min x-max y-min y-max
  <span style="color: #b22222;">;; </span><span style="color: #b22222;">the starting values are already distinct, so we just need to</span>
  <span style="color: #b22222;">;; </span><span style="color: #b22222;">count matching values</span>
<span style="color: #0000ff;">  length</span>
<span style="color: #0000ff;">    map</span> car
<span style="color: #0000ff;">      filter</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cut</span> touches-area? &lt;&gt; x-min x-max y-min y-max
<span style="color: #0000ff;">        map</span><span style="color: #a020f0;"> : </span><span style="color: #0000ff;">cut</span> calculate-trajectory &lt;&gt; x-min x-max y-min
<span style="color: #0000ff;">          map</span> velocities-&gt;particle
<span style="color: #0000ff;">            velocity-parameter-range</span> x-min x-max y-min

<span style="color: #0000ff;">apply</span> count-distinct-parameters
<span style="color: #0000ff;">  parse-input</span> <span style="color: #8b2252;">"target area: x=20..30, y=-10..-5"</span>
</code></pre>
</div>
]]></description>
</item>
</channel>
</rss>
