<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title></title>
    <link rel="self" type="application/atom+xml" href="https://weitzel.dev/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://weitzel.dev"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-02-23T00:00:00+00:00</updated>
    <id>https://weitzel.dev/atom.xml</id>
    <entry xml:lang="en">
        <title>Trampolines and algebraic Fibonacci in Rust</title>
        <published>2026-02-23T00:00:00+00:00</published>
        <updated>2026-02-23T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/rustlang-trampoline/"/>
        <id>https://weitzel.dev/blog/rustlang-trampoline/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/rustlang-trampoline/">&lt;p&gt;In previous articles, we explored &lt;strong&gt;tail recursion&lt;&#x2F;strong&gt; and the &lt;strong&gt;trampoline device&lt;&#x2F;strong&gt; in JavaScript and Go as a workaround for missing tail call optimization (TCO).&lt;&#x2F;p&gt;
&lt;p&gt;This article continues the idea, but now in &lt;strong&gt;Rust&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Rust is interesting here because it makes the algebraic structure explicit.&lt;&#x2F;p&gt;
&lt;p&gt;In this post, we’ll clarify whether Rust supports TCO, implement a trampoline in idiomatic Rust, write a generic Fibonacci implementation, and finally compute Fibonacci numbers over &lt;strong&gt;strings&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;does-rust-support-tail-call-optimization&quot;&gt;Does Rust support tail call optimization?&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Rust does not guarantee tail call optimization.&lt;&#x2F;strong&gt;
Even if a function is tail-recursive, you must assume that each recursive call consumes stack space.&lt;&#x2F;p&gt;
&lt;p&gt;Why?&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Rust compiles via LLVM, which &lt;em&gt;may&lt;&#x2F;em&gt; eliminate tail calls but does not guarantee it.&lt;&#x2F;li&gt;
&lt;li&gt;Rust has deterministic destruction (&lt;code&gt;Drop&lt;&#x2F;code&gt;), which may require stack frames to remain alive.&lt;&#x2F;li&gt;
&lt;li&gt;Rust favors predictable performance over implicit optimizations.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Deep recursion in Rust can overflow the stack.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;If we want recursion without stack growth, we can use the same workaround mentioned in the previous articles:
a trampoline.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;return-of-the-trampoline&quot;&gt;Return of the trampoline&lt;&#x2F;h2&gt;
&lt;p&gt;Instead of calling itself recursively, a function returns a &lt;strong&gt;thunk&lt;&#x2F;strong&gt;. That is a function describing the next step.
A trampoline repeatedly executes these steps until a final value appears.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-trampoline&quot;&gt;The trampoline&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;enum&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Bounce&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    Done&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    More&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;dyn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; FnOnce&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Bounce&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; trampoline&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; b&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Bounce&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    loop&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;        b&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; b&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;            Bounce&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Done&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; value&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;            Bounce&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;More&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;step&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; step&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Despite the name, nothing magical happens here:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Done(value)&lt;&#x2F;code&gt; → computation finished&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;More(step)&lt;&#x2F;code&gt; → keep going&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The loop replaces recursion.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tail-recursive-fibonacci-as-state&quot;&gt;Tail-recursive Fibonacci as state&lt;&#x2F;h2&gt;
&lt;p&gt;If we look back at the tail-recursive logic from the first post:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(previous, current) → (current, previous + current)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Instead of building stack frames, we carry forward &lt;strong&gt;state&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-generic-fibonacci&quot;&gt;A generic Fibonacci&lt;&#x2F;h2&gt;
&lt;p&gt;Fibonacci needs only an addition-like operation and two seed values. No ordering, no multiplication, not even numbers in the usual sense.&lt;&#x2F;p&gt;
&lt;p&gt;In Rust, we can express this precisely.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ops&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Add&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; fib_thunk&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; f0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; f1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Bounce&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Add&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Output&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    T&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;static&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;        0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Bounce&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Done&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;f0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;        1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Bounce&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Done&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;f1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;        _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Bounce&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;More&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Box&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;move&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; next&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;f0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;f1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;            fib_thunk&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; f1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; next&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; f0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; f1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Add&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Output&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    T&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;static&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    trampoline&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;fib_thunk&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; f0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; f1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We chose a &lt;code&gt;&#x27;static&lt;&#x2F;code&gt; trait object for simplicity. This prevents using &lt;code&gt;T&lt;&#x2F;code&gt; that borrows non-&lt;code&gt;&#x27;static&lt;&#x2F;code&gt; data.
If we parameterized &lt;code&gt;Bounce&lt;&#x2F;code&gt; with a lifetime, we could remove the &lt;code&gt;&#x27;static&lt;&#x2F;code&gt; bound.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-does-this-bound-mean&quot;&gt;What does this bound mean?&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Add&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Output&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It says:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;references to &lt;code&gt;T&lt;&#x2F;code&gt; can be added together to produce a new &lt;code&gt;T&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This is exactly what large mathematical types do:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;big integers&lt;&#x2F;li&gt;
&lt;li&gt;rational numbers&lt;&#x2F;li&gt;
&lt;li&gt;matrices&lt;&#x2F;li&gt;
&lt;li&gt;vectors&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;We only &lt;em&gt;read&lt;&#x2F;em&gt; values and create a new result. No mutation required.&lt;&#x2F;p&gt;
&lt;p&gt;This code now works for e.g. &lt;code&gt;num_bigint::BigInt&lt;&#x2F;code&gt; without changing a single line of logic.
It&#x27;s the kind of abstraction Rust’s trait system was designed to express.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fibonacci-is-algebra-not-arithmetic&quot;&gt;Fibonacci is algebra, not arithmetic&lt;&#x2F;h2&gt;
&lt;p&gt;At this point we can state the key insight:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The Fibonacci algorithm does not fundamentally operate on integers.
It operates on any type whose references support addition.
Rust’s trait system allows us to express this algebraic requirement precisely.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Mathematically, Fibonacci works for any structure with an addition operation.
Rust lets us encode that idea directly in the type system.&lt;&#x2F;p&gt;
&lt;p&gt;If Fibonacci truly depends only on addition, then numbers should be optional. Let’s test that claim.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-surprising-example-fibonacci-over-strings&quot;&gt;A surprising example: Fibonacci over strings&lt;&#x2F;h2&gt;
&lt;p&gt;Rust prevents us from implementing:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;amp;String + &amp;amp;String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;directly because of the orphan rule:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;You may implement a trait for a type only if either the trait or the type is defined in your crate.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;If both the trait and the type come from other crates, the implementation is forbidden.&lt;&#x2F;p&gt;
&lt;p&gt;But we can wrap &lt;code&gt;String&lt;&#x2F;code&gt; in our own type.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-cat-type&quot;&gt;The &lt;code&gt;Cat&lt;&#x2F;code&gt; type&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Clone&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Debug&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Cat&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; From&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Cat&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        Self&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_owned&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Add&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;b&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Cat&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Cat&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    type&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Output&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Cat&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; rhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;b&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Cat&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Cat&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; out&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;            String&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;with_capacity&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; rhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;        out&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;push_str&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;        out&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;push_str&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;rhs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        Cat&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;out&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Addition now means &lt;strong&gt;concatenation&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ab + cd = abcd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;fibonacci-but-with-cats&quot;&gt;Fibonacci, but with cats&lt;&#x2F;h2&gt;
&lt;p&gt;Let’s compute:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;F(0) = me&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;F(1) = ow&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; result&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;        6&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        Cat&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;me&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        Cat&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ow&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:?&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; result&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;step-by-step&quot;&gt;Step-by-step&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;term&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: left&quot;&gt;value&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;F₀&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;me&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;F₁&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;ow&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;F₂&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;meow&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;F₃&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;owmeow&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;F₄&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;meowowmeow&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;F₅&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;owmeowmeowowmeow&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;F₆&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;meowowmeowowmeowmeowowmeow&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;The &lt;strong&gt;structure&lt;&#x2F;strong&gt; follows Fibonacci exactly.
Only the meaning of addition changed.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-algebra-hiding-underneath&quot;&gt;The algebra hiding underneath&lt;&#x2F;h2&gt;
&lt;p&gt;Notice that the code doesn&#x27;t care about numbers. By using the &lt;code&gt;Add&lt;&#x2F;code&gt; trait, we&#x27;ve generalized the algorithm into an algebraic structure:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(T, +)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Any type that defines addition can generate a Fibonacci sequence.
Rust’s trait bounds let us express this requirement exactly.
This is the FP move: define the algorithm by its required structure, not by a concrete type.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-this-costs-us&quot;&gt;What this costs us&lt;&#x2F;h2&gt;
&lt;p&gt;While the trampoline saves your stack, it’s not free. You’re trading stack space for heap allocations by boxing a
closure on every single step. If you need a high-performance Fibonacci in Rust, you’d use a &lt;code&gt;for&lt;&#x2F;code&gt; loop. We’re doing this
for the conceptual elegance and the TCO workaround.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-future-explicit-tail-calls&quot;&gt;The future: explicit tail calls&lt;&#x2F;h2&gt;
&lt;p&gt;While we can use trampolines today, there is a keyword for this exact purpose: &lt;code&gt;become&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In future versions of Rust, we could potentially replace our &lt;code&gt;Bounce&lt;&#x2F;code&gt; enum and heap-allocated &lt;code&gt;Box&lt;&#x2F;code&gt; closures with a single keyword that guarantees the stack frame is reused:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Potential future syntax&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; fib_native&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; f0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; f1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    T&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Add&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Output&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;        0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; f0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;        1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; f1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;        _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; become&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; fib_native&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; f1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; f0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; f1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It eliminates the performance penalty of heap allocations.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;landing-on-four-feet&quot;&gt;Landing on four feet&lt;&#x2F;h2&gt;
&lt;p&gt;Trampolines began as a workaround for missing tail call optimization.
In Rust, they reveal something deeper.
A tail-recursive function is really a state machine in disguise.
Once the recursion disappears, what remains is algebra: values evolving under an operation.&lt;&#x2F;p&gt;
&lt;p&gt;Fibonacci never depended on integers. We only assumed it did.&lt;&#x2F;p&gt;
&lt;p&gt;Rust’s type system lets us remove that assumption and state exactly what the algorithm requires.
And once you see that, Fibonacci stops being a numerical algorithm and becomes a structural one.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Four architectures, one system</title>
        <published>2026-02-20T00:00:00+00:00</published>
        <updated>2026-02-20T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/four-architectures/"/>
        <id>https://weitzel.dev/blog/four-architectures/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/four-architectures/">&lt;blockquote&gt;
&lt;p&gt;Infrastructure waits quietly - until everyone needs it at once.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;In early 2015, I built a scheduling system that was supposed to replace a shared spreadsheet. It is still running today.
During those eleven years, the software was rewritten four times. Not because it failed, not because new technology
appeared, and not because performance demanded it, but because reality revealed that the problems worth solving were
different from the ones I had originally optimized for.&lt;&#x2F;p&gt;
&lt;p&gt;This is the story of how a small prototype for one group of doctors evolved into a long-running production system, and
why every rewrite made it simpler.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-small-problem&quot;&gt;A small problem&lt;&#x2F;h2&gt;
&lt;p&gt;The project began with a complaint.&lt;&#x2F;p&gt;
&lt;p&gt;My brother, a physician participating in the &lt;em&gt;Ärztlicher Notdienst&lt;&#x2F;em&gt; in a German federal state, was dissatisfied with how
shifts were assigned. The regional organization generated rosters using a round-robin scheme based on an alphabetically
ordered list of doctors. Administratively simple, but practically frustrating: vacations, family events, and
professional obligations were ignored. Doctors spent significant effort trading shifts afterward to make schedules
workable.&lt;&#x2F;p&gt;
&lt;p&gt;He asked whether doctors could organize the roster themselves. The first users were a single region - a few hundred
physicians coordinating emergency duty around one hospital network. The problem looked small. The first attempt
resembled little more than a structured alternative to a shared Google spreadsheet.&lt;&#x2F;p&gt;
&lt;p&gt;I expected a hobby project.&lt;&#x2F;p&gt;
&lt;p&gt;Instead, adoption spread quickly. Other regions joined after hearing how much organizational friction disappeared. The
most surprising discovery was not technical at all: a relatively small piece of software solved a coordination problem
that had persisted inside a large institution for years.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;architecture-1-a-prototype-that-escaped&quot;&gt;Architecture 1: a prototype that escaped&lt;&#x2F;h2&gt;
&lt;p&gt;To build something quickly, I reused a CMS platform I had co-developed years earlier as founder and CTO of a startup.
The company had closed in 2002, but the software (a Java-based CMS) remained privately maintained.&lt;&#x2F;p&gt;
&lt;p&gt;It was available, familiar, and adaptable. That was enough.&lt;&#x2F;p&gt;
&lt;p&gt;The initial system:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;CMS-based application&lt;&#x2F;li&gt;
&lt;li&gt;interpreted environment&lt;&#x2F;li&gt;
&lt;li&gt;SQL database backend&lt;&#x2F;li&gt;
&lt;li&gt;single tenant&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Speed mattered more than architecture. The goal was validation.&lt;&#x2F;p&gt;
&lt;p&gt;The prototype worked well enough that it entered production and stayed there for more than two years. Growth exposed its
limits. Additional regions required isolation of users, schedules, and workflows. Multi-tenancy was unavoidable.&lt;&#x2F;p&gt;
&lt;p&gt;The first real rewrite began.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;architecture-2-doing-it-properly&quot;&gt;Architecture 2: doing it properly&lt;&#x2F;h2&gt;
&lt;p&gt;In December 2017, I rebuilt the system using a conservative and well-understood stack:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Kotlin on the JVM&lt;&#x2F;li&gt;
&lt;li&gt;Ktor 0.9.5, one of the final pre-1.0 releases&lt;&#x2F;li&gt;
&lt;li&gt;Tomcat application server&lt;&#x2F;li&gt;
&lt;li&gt;JDBC persistence&lt;&#x2F;li&gt;
&lt;li&gt;MySQL database&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The objective was straightforward: transform a successful prototype into a maintainable multi-tenant system. The rewrite
itself was uneventful. The system entered production and operated reliably for about a year.&lt;&#x2F;p&gt;
&lt;p&gt;Then the system encountered its first real failure.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-incident&quot;&gt;The incident&lt;&#x2F;h2&gt;
&lt;p&gt;At the start of a booking phase - the busiest minutes of the entire scheduling cycle - the database became corrupted.
The shift table became unreadable. A backup system existed and functioned correctly. Recovery took roughly fifteen
minutes.&lt;&#x2F;p&gt;
&lt;p&gt;Technically acceptable&lt;&#x2F;p&gt;
&lt;p&gt;Operationally disastrous.&lt;&#x2F;p&gt;
&lt;p&gt;During booking openings, hundreds of doctors attempt to reserve preferred shifts simultaneously. Fairness depends on
responsiveness in those first minutes. A fifteen-minute outage destroyed that assumption. Shortly after recovery, the
corruption happened again.&lt;&#x2F;p&gt;
&lt;p&gt;The failure revealed something unexpected: The problem was not availability. The problem was recovery time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;architecture-3-removing-the-database&quot;&gt;Architecture 3: removing the database&lt;&#x2F;h2&gt;
&lt;p&gt;In December 2018, persistence moved from a relational database to the filesystem. Recovery became an atomic file
replacement. Instant.&lt;&#x2F;p&gt;
&lt;p&gt;This eliminated the dominant failure mode but transferred responsibility for consistency into the application itself.
Access to tenant data had to be synchronized:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;reads remained concurrent,&lt;&#x2F;li&gt;
&lt;li&gt;writes were serialized per tenant,&lt;&#x2F;li&gt;
&lt;li&gt;requests occasionally waited during heavy activity.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Latency increased slightly but remained below &lt;strong&gt;500 ms&lt;&#x2F;strong&gt; even during peak load for the largest region with approx. 500
participants.&lt;&#x2F;p&gt;
&lt;p&gt;The optimization target had changed.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Before&lt;&#x2F;th&gt;&lt;th&gt;After&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;maximize concurrency&lt;&#x2F;td&gt;&lt;td&gt;minimize recovery time&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;database-managed consistency&lt;&#x2F;td&gt;&lt;td&gt;application-managed consistency&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;complex restore&lt;&#x2F;td&gt;&lt;td&gt;instant recovery&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;The filesystem was not superior in general. It would have been the wrong choice for tens of thousands of users. But it
was superior for &lt;strong&gt;this&lt;&#x2F;strong&gt; workload.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;history-as-a-side-effect&quot;&gt;History as a side effect&lt;&#x2F;h2&gt;
&lt;p&gt;Each modification wrote a new backup file alongside the primary data file. Over a booking season:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;approx. 500 doctors participate&lt;&#x2F;li&gt;
&lt;li&gt;roughly 3,000 shifts exist&lt;&#x2F;li&gt;
&lt;li&gt;a little more than 4,000 history files accumulate through cancellations and rebookings&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The database version also logged activity - but those logs vanished together with corrupted data. Filesystem backups,
copied asynchronously to independent storage, survived runtime failures.&lt;&#x2F;p&gt;
&lt;p&gt;The improvement was not absolute safety but separation of failure domains. Backup moved outside the request path. The
system unintentionally gained a transparent history of decisions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;stability&quot;&gt;Stability&lt;&#x2F;h2&gt;
&lt;p&gt;After the filesystem rewrite, the system stabilized.&lt;&#x2F;p&gt;
&lt;p&gt;It runs today on a Netcup Root Server (4 cores, 16 GB RAM, Ubuntu Linux), operating below 10% CPU during peak booking
phases. Memory usage remains under 8 GB. Users rarely noticed deployments. Interfaces remained stable. Updates were
scheduled during off-hours; writes paused briefly while reads continued uninterrupted. Major incidents disappeared. Only
one long-uptime Ktor session bug required introducing a scheduled reboot every couple of weeks.&lt;&#x2F;p&gt;
&lt;p&gt;Otherwise, the system simply ran. For years.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;architecture-4-when-time-becomes-the-problem&quot;&gt;Architecture 4: when time becomes the problem&lt;&#x2F;h2&gt;
&lt;p&gt;The next rewrite was not triggered by failure but by aging dependencies.&lt;&#x2F;p&gt;
&lt;p&gt;The Kotlin&#x2F;Ktor&#x2F;Tomcat stack depended on early ecosystem libraries. Some repositories disappeared. Builds survived only because I backed up my local Maven &lt;code&gt;.m2&lt;&#x2F;code&gt; cache.&lt;&#x2F;p&gt;
&lt;p&gt;The application became locked to:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Ktor 1.6.x&lt;&#x2F;li&gt;
&lt;li&gt;old dependencies&lt;&#x2F;li&gt;
&lt;li&gt;Tomcat 8&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Upgrading further was impossible. The system was stable - but frozen. Evolvability had vanished.&lt;&#x2F;p&gt;
&lt;p&gt;In December 2025, I performed the final rewrite:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;modern Kotlin&lt;&#x2F;li&gt;
&lt;li&gt;current Ktor&lt;&#x2F;li&gt;
&lt;li&gt;embedded Netty server&lt;&#x2F;li&gt;
&lt;li&gt;standalone deployment&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Tomcat disappeared. WAR packaging disappeared. Dependency surface shrank dramatically. Deployment became a simple
scripted restart of a &lt;code&gt;systemd&lt;&#x2F;code&gt; service. Functionality remained unchanged. The rewrite restored the ability to evolve.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-changed-and-what-didn-t&quot;&gt;What changed and what didn’t&lt;&#x2F;h2&gt;
&lt;p&gt;Across eleven years, nearly every technical layer changed. The domain did not. Doctors booking shifts fairly among
themselves remained constant. The core model survived four complete rewrites almost untouched.&lt;&#x2F;p&gt;
&lt;p&gt;Each rewrite removed a layer whose original benefit had expired:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Rewrite&lt;&#x2F;th&gt;&lt;th&gt;Removed Constraint&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;CMS → Kotlin&lt;&#x2F;td&gt;&lt;td&gt;framework limitations&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Database → filesystem&lt;&#x2F;td&gt;&lt;td&gt;slow recovery&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Tomcat → Netty&lt;&#x2F;td&gt;&lt;td&gt;dependency lock-in&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;The system did not become more sophisticated. It became smaller.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;eleven-years&quot;&gt;Eleven years&lt;&#x2F;h2&gt;
&lt;p&gt;Three things surprised me.&lt;&#x2F;p&gt;
&lt;p&gt;First, how a small coordination problem could spread organically once solved well. Second, that serious failures
appeared where I least expected them - not in complex logic, but in infrastructure assumptions. Third, that longevity
rewards simplicity more than sophistication.&lt;&#x2F;p&gt;
&lt;p&gt;Long-lived systems optimize for properties that are easy to underestimate at the beginning:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;recoverability matters more than uptime,&lt;&#x2F;li&gt;
&lt;li&gt;operational simplicity matters more than architectural completeness,&lt;&#x2F;li&gt;
&lt;li&gt;evolvability matters more than technological modernity,&lt;&#x2F;li&gt;
&lt;li&gt;smaller dependency surfaces age better.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The project began as an alternative to a shared spreadsheet for one group of doctors. It still runs today - simpler than
before, and closer to the problem it was meant to solve.&lt;&#x2F;p&gt;
&lt;p&gt;Software longevity, I learned, is less about choosing the right architecture at the beginning and more about removing
what turns out not to matter.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Adding audio to your blog</title>
        <published>2026-02-11T00:00:00+00:00</published>
        <updated>2026-02-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/audio-player-shortcode/"/>
        <id>https://weitzel.dev/blog/audio-player-shortcode/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/audio-player-shortcode/">&lt;p&gt;There are two practical ways to add audio to a blog: use the native &lt;code&gt;&amp;lt;audio&amp;gt;&lt;&#x2F;code&gt; element or render a custom player with JavaScript.
The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;&quot;&gt;Zola&lt;&#x2F;a&gt; theme &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;thomasweitzel&#x2F;zolarwind&quot;&gt;Zolarwind&lt;&#x2F;a&gt; provides two shortcodes that map to those choices: &lt;code&gt;audio_simple&lt;&#x2F;code&gt; uses the native element, &lt;code&gt;audio&lt;&#x2F;code&gt; uses a custom player.
Both are usable as-is, and the choice comes down to how much control you want over the player UI.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-baseline-native-audio&quot;&gt;The baseline native &lt;code&gt;&amp;lt;audio&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You get built-in controls and good accessibility.
If you are fine with browser-native styling, this is the fastest path.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;audio&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt; controls&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;source&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt; src&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;audio.mp3&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt; type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;audio&#x2F;mpeg&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;audio&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;audio controls&gt;
  &lt;source src=&quot;resources&#x2F;media&#x2F;audio.mp3&quot; type=&quot;audio&#x2F;mpeg&quot;&gt;
&lt;&#x2F;audio&gt;
&lt;p&gt;The tradeoff is consistency. Browsers style the element differently, and you get limited control over the UI.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;audio-simple-shortcode&quot;&gt;&lt;code&gt;audio_simple&lt;&#x2F;code&gt; shortcode&lt;&#x2F;h2&gt;
&lt;p&gt;This wraps the native element and keeps the setup small.
It uses no JavaScript, like the baseline audio element, but adds a small amount of CSS for layout.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{{ audio_simple(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  src&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;audio.mp3&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  title&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Audio in your blog&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  year&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2026&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  artist&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Female Speaker&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  label&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Blog of Thomas Weitzel&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;) }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;div class=&quot;container max-w-md my-6 py-6 px-6 text-black dark:text-black bg-gradient-to-tr from-ok-600 to-primary-800 rounded-2xl overflow-hidden&quot;&gt;
    &lt;div class=&quot;text-center relative&quot;&gt;
        &lt;svg xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot; stroke-width=&quot;1.5&quot; stroke=&quot;currentColor&quot; class=&quot;h-16 w-16 inline-block&quot;&gt;
            &lt;path stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot; d=&quot;M12 18.75a6 6 0 006-6v-1.5m-6 7.5a6 6 0 01-6-6v-1.5m6 7.5v3.75m-3.75 0h7.5M12 15.75a3 3 0 01-3-3V4.5a3 3 0 116 0v8.25a3 3 0 01-3 3z&quot; &#x2F;&gt;
        &lt;&#x2F;svg&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;mb-6 text-center relative&quot;&gt;
        &lt;h2 class=&quot;inline-block font-medium&quot;&gt;Audio in your blog&lt;&#x2F;h2&gt;
        &lt;p class=&quot;inline-block font-medium text-sm&quot;&gt;Female Speaker | Blog of Thomas Weitzel | 2026&lt;&#x2F;p&gt;
    &lt;&#x2F;div&gt;
    &lt;audio controls src=&quot;resources&amp;#x2F;media&amp;#x2F;audio.mp3&quot; style=&quot;width: 100%&quot;&gt;Your browser does not support the audio element.&lt;&#x2F;audio&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;custom-player&quot;&gt;Custom player&lt;&#x2F;h2&gt;
&lt;p&gt;If you want a consistent player UI across browsers, the &lt;code&gt;audio&lt;&#x2F;code&gt; shortcode renders a custom player with JavaScript.
The native &lt;code&gt;&amp;lt;audio&amp;gt;&lt;&#x2F;code&gt; controls are not used; the UI is fully custom.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{{ audio(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  src&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;audio.mp3&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  length&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0:48&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  title&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Audio in your blog&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  year&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2026&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  artist&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Female Speaker&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  label&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Blog of Thomas Weitzel&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;) }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;div
  class=&quot;container max-w-md my-6 py-6 px-6 text-black dark:text-black bg-gradient-to-tr from-primary-600 to-warn-800 rounded-2xl overflow-hidden&quot;
  data-audio-id=&quot;1&quot;
  data-audio-src=&quot;resources&amp;#x2F;media&amp;#x2F;audio.mp3&quot;
&gt;
    &lt;div class=&quot;text-center relative&quot;&gt;
        &lt;svg xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot; stroke-width=&quot;1.5&quot; stroke=&quot;currentColor&quot; class=&quot;h-16 w-16 inline-block&quot;&gt;
            &lt;path stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot; d=&quot;M12 18.75a6 6 0 006-6v-1.5m-6 7.5a6 6 0 01-6-6v-1.5m6 7.5v3.75m-3.75 0h7.5M12 15.75a3 3 0 01-3-3V4.5a3 3 0 116 0v8.25a3 3 0 01-3 3z&quot; &#x2F;&gt;
        &lt;&#x2F;svg&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;mb-6 text-center relative&quot;&gt;
        &lt;h2 class=&quot;inline-block font-medium&quot;&gt;Audio in your blog&lt;&#x2F;h2&gt;
        &lt;p class=&quot;inline-block font-medium text-sm&quot;&gt;Female Speaker | Blog of Thomas Weitzel | 2026&lt;&#x2F;p&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;audio-controls1 flex space-x-1&quot;&gt;
        &lt;div class=&quot;play-div1 flex-none hover:text-fail-600&quot;&gt;Loading ...&lt;&#x2F;div&gt;
        &lt;div class=&quot;time-div1 flex-none pr-2&quot;&gt;00:00 | 0:48&lt;&#x2F;div&gt;
        &lt;div class=&quot;flex-auto cursor-pointer select-none mt-2&quot;&gt;
            &lt;div class=&quot;progress-container1 w-full bg-primary-700 rounded-full h-2 dark:bg-neutral-200&quot;&gt;
                &lt;div class=&quot;progress-bar1 bg-neutral-800 h-2 rounded-full hover:bg-fail-600&quot; style=&quot;width: 0%&quot;&gt;&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
        &lt;div class=&quot;speaker-div1 flex-none pl-2 hover:text-fail-600&quot;&gt;&lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;&lt;script src=&quot;https:&#x2F;&#x2F;weitzel.dev&#x2F;js&#x2F;audio&#x2F;howler.js&quot; integrity=&quot;sha384-B3AhJtVepaXjzRprLH6ZMkrOI+XDduqXmwhe4m+RDATUkM8o1I2STFsig6dra4XF&quot;&gt;&lt;&#x2F;script&gt;
        &lt;script src=&quot;https:&#x2F;&#x2F;weitzel.dev&#x2F;js&#x2F;audio&#x2F;audio-player.js&quot; integrity=&quot;sha384-uM+RjXS&amp;#x2F;SiYym8NXLgoHFdNXVU0dZFjg9FyWhppQgkb0RJd1dnp7H+Pom5azyaMI&quot;&gt;&lt;&#x2F;script&gt;
        &lt;script src=&quot;https:&#x2F;&#x2F;weitzel.dev&#x2F;js&#x2F;audio&#x2F;audio-init.js&quot; integrity=&quot;sha384-MxFc2CYeIiCM4XDzrORmIy9R06BD&amp;#x2F;FQLTHq71ZIlTY&amp;#x2F;tJCqi3Isa8&amp;#x2F;o+yKSFg1Vc&quot;&gt;&lt;&#x2F;script&gt;&lt;&#x2F;div&gt;
&lt;p&gt;I prefer the &lt;code&gt;audio&lt;&#x2F;code&gt; shortcode, because I want a stable player UI across browsers.
&lt;code&gt;audio_simple&lt;&#x2F;code&gt; stays in the toolbox because it keeps the setup small and uses no extra JavaScript.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;The shortcodes expect local assets, not remote URLs.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;zola serve&lt;&#x2F;code&gt; does not support range requests as of 0.22.1, so Chrome cannot seek properly. Use a static server for testing.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Search</title>
        <published>2026-01-14T00:00:00+00:00</published>
        <updated>2026-01-14T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/pages/search/"/>
        <id>https://weitzel.dev/pages/search/</id>
        
        <content type="html" xml:base="https://weitzel.dev/pages/search/"></content>
        
    </entry>
    <entry xml:lang="en">
        <title>Static lifetimes and factories</title>
        <published>2025-06-25T00:00:00+00:00</published>
        <updated>2025-06-25T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/lifetime-and-static-factories/"/>
        <id>https://weitzel.dev/blog/lifetime-and-static-factories/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/lifetime-and-static-factories/">&lt;p&gt;I&#x27;m just getting used to the Rust borrow checker, and I feel pretty good about it. I&#x27;ve learned that values cannot
outlive the variables they&#x27;re bound to, that the compiler prevents me from accessing data that has been dropped, and
that lifetimes ensure that references remain valid.&lt;&#x2F;p&gt;
&lt;p&gt;So I write something like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; b&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;world!&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;        c&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; choose&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;c: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; c&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &amp;lt;-- I was expecting a compile-time error here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Return a reference to the longer slice&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; choose&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;s1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; str&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; s2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; str&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; str&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; s1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; s2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; s1&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; s2&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;At first glance, I was confident: &lt;code&gt;b&lt;&#x2F;code&gt; lives in a smaller inner scope, so clearly it cannot be used after it is dropped.
And &lt;code&gt;choose&lt;&#x2F;code&gt; might return &lt;code&gt;&amp;amp;b&lt;&#x2F;code&gt;, so this should not compile.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Wrong. It does compile.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;But why? Because &lt;code&gt;&quot;world!&quot;&lt;&#x2F;code&gt; is a &lt;strong&gt;string literal&lt;&#x2F;strong&gt;, which has a special property in Rust: it has a &lt;code&gt;&#x27;static&lt;&#x2F;code&gt; lifetime.
This means it lives for the &lt;strong&gt;entire duration of the program&lt;&#x2F;strong&gt;. It’s not just some stack value, but it’s embedded
directly in the binary.&lt;&#x2F;p&gt;
&lt;p&gt;So when you write:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; b&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;world!&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; type: &amp;amp;&amp;#39;static str&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You’re assigning a reference that’s already &lt;code&gt;&#x27;static&lt;&#x2F;code&gt;, even though &lt;code&gt;b&lt;&#x2F;code&gt;, the variable itself, goes out of scope. So
&lt;code&gt;choose(&amp;amp;a, &amp;amp;b)&lt;&#x2F;code&gt; returns a &lt;code&gt;&amp;amp;&#x27;static str&lt;&#x2F;code&gt;, and &lt;code&gt;c&lt;&#x2F;code&gt; safely points to it, even outside the block where &lt;code&gt;b&lt;&#x2F;code&gt; is defined.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;let-s-produce-the-expected-compile-time-error&quot;&gt;Let&#x27;s produce the expected compile-time error&lt;&#x2F;h2&gt;
&lt;p&gt;Change just one thing:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; String&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; b&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; String&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;world!&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;        c&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; choose&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;c: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; c&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &amp;lt;-- We get a compile-time error here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now it fails to compile. &lt;code&gt;String::from(&quot;world!&quot;)&lt;&#x2F;code&gt; creates a &lt;strong&gt;heap-allocated string&lt;&#x2F;strong&gt;, and &lt;code&gt;&amp;amp;b&lt;&#x2F;code&gt; is only valid as long as
&lt;code&gt;b&lt;&#x2F;code&gt; is in scope. The compiler doesn&#x27;t allow a reference to &lt;code&gt;b&lt;&#x2F;code&gt; to escape its block.&lt;&#x2F;p&gt;
&lt;p&gt;This is exactly what we would expect, but the first example violates that expectation precisely because of the &lt;code&gt;&#x27;static&lt;&#x2F;code&gt;
literal.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;building-a-factory-with-static-references&quot;&gt;Building a factory with &lt;code&gt;&#x27;static&lt;&#x2F;code&gt; references&lt;&#x2F;h2&gt;
&lt;p&gt;Let’s try something similar to the earlier scope example. What if I allocate a string inside a block, but want to use it
&lt;strong&gt;safely&lt;&#x2F;strong&gt; outside?&lt;&#x2F;p&gt;
&lt;p&gt;This would usually fail:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; String&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Rust&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;as_str&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &amp;lt;-- name is dropped here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;  println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &amp;lt;-- ERROR: use of borrowed value after move&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now here’s the twist. If I replace the heap allocation with a leaked one, it compiles and runs:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;static&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; str&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;leak&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Rust&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;into_boxed_str&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;        s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; name&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &amp;lt;-- Works fine&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It looks like &lt;code&gt;name&lt;&#x2F;code&gt; goes out of scope, but since we’ve leaked the box, the string is never freed. &lt;code&gt;s&lt;&#x2F;code&gt; holds a &lt;code&gt;&#x27;static&lt;&#x2F;code&gt;
reference to the leaked memory, and the compiler is happy.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;Box::leak&lt;&#x2F;code&gt; turns a heap allocation into a &lt;code&gt;&#x27;static&lt;&#x2F;code&gt; reference by &lt;strong&gt;intentionally leaking&lt;&#x2F;strong&gt; memory. Rust will never free
that memory. The box is consumed, and only a reference is returned.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;but-can-i-drop-it-later&quot;&gt;But can I drop it later?&lt;&#x2F;h2&gt;
&lt;p&gt;No. Once you leak memory with &lt;code&gt;Box::leak&lt;&#x2F;code&gt;, it’s &lt;strong&gt;yours forever&lt;&#x2F;strong&gt;. You can&#x27;t &lt;code&gt;drop()&lt;&#x2F;code&gt; the value anymore, because you&#x27;ve
lost ownership. All you have is a reference, and references don&#x27;t manage memory.&lt;&#x2F;p&gt;
&lt;p&gt;If you need reclaimable memory, consider using an arena allocator or keep the &lt;code&gt;Box&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; somewhere you can access it later
and manually free it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;i-learned-something&quot;&gt;I learned something&lt;&#x2F;h2&gt;
&lt;p&gt;What started with the expectation &quot;This &lt;em&gt;should&lt;&#x2F;em&gt; fail to compile, but doesn&#x27;t&quot; turned out to be a lesson in the
subtleties of Rust’s lifetime system:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;String literals&lt;&#x2F;strong&gt; and other constants live &lt;code&gt;&#x27;static&lt;&#x2F;code&gt;, and sometimes trick you into thinking scopes matter more than
they do.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Heap-allocated values&lt;&#x2F;strong&gt; (like &lt;code&gt;String&lt;&#x2F;code&gt;) behave differently. They won&#x27;t let you sneak references across lifetimes.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Box::leak&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; is a powerful but risky tool: it gives you &lt;code&gt;&#x27;static&lt;&#x2F;code&gt; references to dynamic values, but at the cost of
memory you can never get back.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So yes, you can write factory functions that return &lt;code&gt;&#x27;static&lt;&#x2F;code&gt; references. But do you really need to? Most of the time,
borrowing or owning values explicitly is safer and more idiomatic, and your memory won&#x27;t mysteriously grow over time.&lt;&#x2F;p&gt;
&lt;p&gt;The image above is from &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@mmmarq&quot;&gt;Marcelo Marques&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>How I localized my Hugo theme</title>
        <published>2025-01-02T00:00:00+00:00</published>
        <updated>2025-01-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/l10n-in-hugo/"/>
        <id>https://weitzel.dev/blog/l10n-in-hugo/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/l10n-in-hugo/">&lt;p&gt;When I first decided to localize my Hugo theme, I thought, &lt;em&gt;How hard can it be?&lt;&#x2F;em&gt; But as I dug deeper, I realized there
were more nuances than I had expected, especially with date formatting and pluralization. After some trial and error and
online research, I found effective solutions. I share them here to help you avoid similar obstacles.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;extracting-strings-for-localization&quot;&gt;Extracting Strings for Localization&lt;&#x2F;h2&gt;
&lt;p&gt;The first step was to identify and extract all user-facing text into language files. Hardcoding strings, as shown in the
example below, makes the theme inflexible:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Published on {{ .Date.Format &amp;quot;January 2, 2006&amp;quot; }}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I replaced the hardcoded &lt;code&gt;Published on&lt;&#x2F;code&gt; with a call to Hugo&#x27;s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gohugo.io&#x2F;functions&#x2F;lang&#x2F;translate&#x2F;&quot;&gt;&lt;code&gt;i18n&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
function, which retrieves translations from language files based on the active language setting:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;{{ i18n &amp;quot;published_on&amp;quot; }} {{ .Date.Format &amp;quot;January 2, 2006&amp;quot; }}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To manage translations and get started, I set up an &lt;code&gt;i18n&lt;&#x2F;code&gt; directory and added &lt;code&gt;en.yaml&lt;&#x2F;code&gt; as the first language file:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Date Format&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ate_format&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;January 02, 2006&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Single Post&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ublished_on&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Published on&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;eading_time&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;reading time&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; m&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;inutes&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;minutes&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For German, I created &lt;code&gt;de.yaml&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Date Format&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ate_format&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2. January 2006&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Single Post&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ublished_on&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Veröffentlicht am&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;eading_time&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Lesezeit&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; m&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;inutes&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Minuten&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This structure kept the translations organized and easy to manage.&lt;&#x2F;p&gt;
&lt;p&gt;You should extract all hardcoded strings from your theme&#x27;s template files and store&#x2F;translate them in the language
files. Key elements to extract strings from include:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Navigation labels&lt;&#x2F;li&gt;
&lt;li&gt;Buttons&lt;&#x2F;li&gt;
&lt;li&gt;Dates and times&lt;&#x2F;li&gt;
&lt;li&gt;Informational messages&lt;&#x2F;li&gt;
&lt;li&gt;Error messages&lt;&#x2F;li&gt;
&lt;li&gt;Tooltips and &lt;code&gt;alt&lt;&#x2F;code&gt; text for images&lt;&#x2F;li&gt;
&lt;li&gt;Forms and placeholders&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In the language files, use descriptive keys like &lt;code&gt;post_comment_button&lt;&#x2F;code&gt; instead of vague ones like &lt;code&gt;button&lt;&#x2F;code&gt;, to keep
translations clear and maintainable. If it improves clarity, add a comment.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;formatting-dates-in-a-localized-way&quot;&gt;Formatting Dates in a Localized Way&lt;&#x2F;h2&gt;
&lt;p&gt;Formatting dates for localization proved trickier than expected. I initially tried:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;{{ i18n &amp;quot;published_on&amp;quot; }} {{ .Date.Local.Format (i18n &amp;quot;date_format&amp;quot;) }}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But this didn’t work as intended. Month names remained in English, even with the &lt;code&gt;defaultContentLanguage&lt;&#x2F;code&gt; set to German.
This is because &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gohugo.io&#x2F;methods&#x2F;time&#x2F;format&#x2F;&quot;&gt;&lt;code&gt;.Date.Local.Format&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; only applies the format string without
translating month names or other language-specific elements, making it unsuitable for full localization.&lt;&#x2F;p&gt;
&lt;p&gt;At first, I couldn’t figure out why my dates still showed &lt;code&gt;January&lt;&#x2F;code&gt; or &lt;code&gt;March&lt;&#x2F;code&gt; instead of &lt;code&gt;Januar&lt;&#x2F;code&gt; or &lt;code&gt;März&lt;&#x2F;code&gt;. Because I
didn&#x27;t know better, I tried to use the German word for &lt;code&gt;January&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ate_format&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2. Januar 2006&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This didn&#x27;t yield the expected results either. Every month became &lt;code&gt;Januar&lt;&#x2F;code&gt; now. After some reading, I found that the
correct approach was to use Hugo’s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gohugo.io&#x2F;functions&#x2F;time&#x2F;format&#x2F;&quot;&gt;&lt;code&gt;dateFormat&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; function:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;{{ i18n &amp;quot;published_on&amp;quot; }} {{ dateFormat (i18n &amp;quot;date_format&amp;quot;) .Date }}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Turns out, Hugo expects the English month names in the &lt;code&gt;date_format&lt;&#x2F;code&gt; key to handle automatic translation. A small but
important detail.&lt;&#x2F;p&gt;
&lt;p&gt;That is why the &lt;code&gt;date_format&lt;&#x2F;code&gt; entry in &lt;code&gt;de.yaml&lt;&#x2F;code&gt; must use the English month name &lt;code&gt;January&lt;&#x2F;code&gt; because the Go programming
language and Hugo rely on this name to handle date formatting and automatic translation to local equivalents.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ate_format&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2. January 2006&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; English month name for automatic translation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you want to know exactly how date formatting works, look at the comment in the Go source file
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;golang&#x2F;go&#x2F;blob&#x2F;master&#x2F;src&#x2F;time&#x2F;format.go#L57&quot;&gt;&lt;code&gt;src&#x2F;time&#x2F;format.go&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Here is a summary of the components of a layout string. Each element shows by&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; example the formatting of an element of the reference time. Only these values&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; are recognized. Text in the layout string that is not recognized as part of&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; the reference time is echoed verbatim during Format and expected to appear&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; verbatim in the input to Parse.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;	Year: &amp;quot;2006&amp;quot; &amp;quot;06&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;	Month: &amp;quot;Jan&amp;quot; &amp;quot;January&amp;quot; &amp;quot;01&amp;quot; &amp;quot;1&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;	Day of the week: &amp;quot;Mon&amp;quot; &amp;quot;Monday&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;	Day of the month: &amp;quot;2&amp;quot; &amp;quot;_2&amp;quot; &amp;quot;02&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;	Day of the year: &amp;quot;__2&amp;quot; &amp;quot;002&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;handling-singular-and-plural-forms&quot;&gt;Handling Singular and Plural Forms&lt;&#x2F;h2&gt;
&lt;p&gt;Pluralization is often overlooked but crucial for localization. Handling singular and plural forms ensures text like
&lt;code&gt;1 minute&lt;&#x2F;code&gt; or &lt;code&gt;5 minutes&lt;&#x2F;code&gt; reads naturally in each language, accommodating linguistic rules. For example, in Polish,
&lt;code&gt;1 minute&lt;&#x2F;code&gt; translates to &lt;code&gt;1 minuta&lt;&#x2F;code&gt;, while &lt;code&gt;2 minutes&lt;&#x2F;code&gt; becomes &lt;code&gt;2 minuty&lt;&#x2F;code&gt;, and &lt;code&gt;5 minutes&lt;&#x2F;code&gt; is &lt;code&gt;5 minut&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;For text that varies based on numbers, like reading time, I initially used this template:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;{{ .ReadingTime }} {{ i18n &amp;quot;minutes&amp;quot; }}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However, this approach failed to handle singular and plural cases. To address this, I defined separate &lt;code&gt;one&lt;&#x2F;code&gt; (singular)
and &lt;code&gt;other&lt;&#x2F;code&gt; (plural) forms in the language files, allowing Hugo to dynamically select the correct form based on the
value.&lt;&#x2F;p&gt;
&lt;p&gt;For &lt;code&gt;en.yaml&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; m&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;inute&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    o&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ne&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;minute&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Singular form&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    o&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ther&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;minutes&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Plural form&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For &lt;code&gt;de.yaml&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; m&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;inute&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    o&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ne&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Minute&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    o&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ther&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Minuten&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Like Polish, certain languages have additional plural forms like &lt;code&gt;zero&lt;&#x2F;code&gt; or &lt;code&gt;few&lt;&#x2F;code&gt;. Refer to
the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.unicode.org&#x2F;cldr&#x2F;charts&#x2F;43&#x2F;supplemental&#x2F;language_plural_rules.html&quot;&gt;Unicode CLDR rules&lt;&#x2F;a&gt; for details.&lt;&#x2F;p&gt;
&lt;p&gt;In the template, I updated the logic to:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&amp;lt;!--&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Dynamically selects singular or plural form based on ReadingTime &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;{{ .ReadingTime }} {{ i18n &amp;quot;minute&amp;quot; .ReadingTime }}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This approach worked perfectly. Hugo automatically chose the correct form based on the value of &lt;code&gt;.ReadingTime&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;testing-the-localization&quot;&gt;Testing the Localization&lt;&#x2F;h2&gt;
&lt;p&gt;To ensure the localization worked as expected, I thoroughly tested the implementation by switching between languages and
verifying edge cases. This process involved checking strings, dates, and plural forms in various scenarios.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;setting-up-the-default-language&quot;&gt;Setting Up the Default Language&lt;&#x2F;h3&gt;
&lt;p&gt;I set the &lt;code&gt;defaultContentLanguage&lt;&#x2F;code&gt; to German in the &lt;code&gt;config.toml&lt;&#x2F;code&gt; file:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;defaultContentLanguage&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;de&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Set the default language to German&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;testing-translated-strings&quot;&gt;Testing Translated Strings&lt;&#x2F;h3&gt;
&lt;p&gt;Running &lt;code&gt;hugo server&lt;&#x2F;code&gt;, I verified that all user-facing strings were translated correctly. For example:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The text &lt;code&gt;Published on&lt;&#x2F;code&gt; displayed as &lt;code&gt;Veröffentlicht am&lt;&#x2F;code&gt; when German was selected.&lt;&#x2F;li&gt;
&lt;li&gt;Navigation labels, buttons, and informational messages all reflected the appropriate translations.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;validating-date-localization&quot;&gt;Validating Date Localization&lt;&#x2F;h3&gt;
&lt;p&gt;Dates were displayed with correctly localized month names, such as &lt;code&gt;Januar&lt;&#x2F;code&gt; and &lt;code&gt;März&lt;&#x2F;code&gt;, adhering to the selected
language. Using &lt;code&gt;dateFormat&lt;&#x2F;code&gt; with the &lt;code&gt;date_format&lt;&#x2F;code&gt; key ensured month names were automatically translated.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;testing-pluralization&quot;&gt;Testing Pluralization&lt;&#x2F;h3&gt;
&lt;p&gt;I tested reading times across different values to ensure the correct singular or plural forms were applied:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;1 Minute&lt;&#x2F;code&gt; for singular.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;5 Minuten&lt;&#x2F;code&gt; for plural. For complex languages like Polish or Arabic, I simulated values such as 0, 1, 2, 5, and 10 to
confirm that the appropriate plural forms (zero, one, other, etc.) were selected based on the rules.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;edge-cases&quot;&gt;Edge Cases&lt;&#x2F;h3&gt;
&lt;p&gt;I tested edge cases such as:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;0 minutes&lt;&#x2F;code&gt; to ensure proper handling of zero plural forms.&lt;&#x2F;li&gt;
&lt;li&gt;Unexpected values like -1 or 1000 to verify the robustness of the implementation.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;These checks confirmed that all user-facing elements adhered to the selected language and its cultural conventions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;lessons-learned&quot;&gt;Lessons Learned&lt;&#x2F;h2&gt;
&lt;p&gt;Looking back, these things made it possible for the theme to adapt to different languages:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Extract user-facing strings into language files using the theme&#x27;s &lt;code&gt;i18n&lt;&#x2F;code&gt; directory.&lt;&#x2F;li&gt;
&lt;li&gt;Use &lt;code&gt;dateFormat&lt;&#x2F;code&gt; for properly localized dates and month names.&lt;&#x2F;li&gt;
&lt;li&gt;Handle singular and plural forms with &lt;code&gt;one&lt;&#x2F;code&gt; and &lt;code&gt;other&lt;&#x2F;code&gt; keys in language files.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Despite some trial and error, localization now makes my Hugo theme more adaptable and easier to tailor to different
languages and users.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Dark theme toggle with Tailwind</title>
        <published>2024-12-10T00:00:00+00:00</published>
        <updated>2024-12-10T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/dark-theme-toggle/"/>
        <id>https://weitzel.dev/blog/dark-theme-toggle/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/dark-theme-toggle/">&lt;p&gt;The ability to toggle between light and dark themes is a key feature in modern web applications.
With &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tailwindcss.com&#x2F;&quot;&gt;Tailwind CSS&lt;&#x2F;a&gt; 4.0, implementing this functionality has become significantly easier
compared to earlier versions like 3.4. The latest version simplifies theming, eliminates the need for manual opacity
handling, and integrates seamlessly with React.&lt;&#x2F;p&gt;
&lt;p&gt;In this blog post, I’ll build a dark theme toggle in a React application using Tailwind CSS 4.0, explain why local
storage is essential, and highlight how the current Tailwind 4.0 beta improves over 3.4.&lt;&#x2F;p&gt;
&lt;p&gt;You can have a look at the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;thomasweitzel.github.io&#x2F;frontend-mentor&#x2F;color-theme-toggle&#x2F;dist&#x2F;&quot;&gt;live demo&lt;&#x2F;a&gt; or
the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;thomasweitzel&#x2F;frontend-mentor&#x2F;tree&#x2F;main&#x2F;color-theme-toggle&quot;&gt;project on GitHub&lt;&#x2F;a&gt;. Here is how it
should look in both modes:&lt;&#x2F;p&gt;
&lt;figure class=&quot;mt-4&quot;&gt;&lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;thomasweitzel.github.io&amp;#x2F;frontend-mentor&amp;#x2F;color-theme-toggle&amp;#x2F;dist&amp;#x2F;&quot; class=&quot;inline-block leading-none&quot;&gt;&lt;img class=&quot;block image-shortcode&quot; src=&quot;https:&#x2F;&#x2F;weitzel.dev&#x2F;blog&#x2F;dark-theme-toggle&#x2F;resources&#x2F;media&#x2F;example.webp&quot; alt=&quot;Collage of Images of Page in Light and Dark Mode&quot; width=&quot;480&quot; height=&quot;500&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;&#x2F;a&gt;
    &lt;figcaption class=&quot;italic&quot;&gt;Click on the image to see the live demo&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;h2 id=&quot;what-s-new-in-tailwind-css-4-0&quot;&gt;What’s New in Tailwind CSS 4.0?&lt;&#x2F;h2&gt;
&lt;p&gt;Tailwind CSS 4.0 introduces significant improvements to theming:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;@theme&lt;&#x2F;code&gt; Directive: You can now declare your theme variables directly in the CSS file, removing the need for
extensive &lt;code&gt;tailwind.config.js&lt;&#x2F;code&gt; setup.&lt;&#x2F;li&gt;
&lt;li&gt;Automatic Opacity Handling: Opacity is automatically integrated into colors, so you don’t need to manually manage
&lt;code&gt;rgb&lt;&#x2F;code&gt; or &lt;code&gt;rgba&lt;&#x2F;code&gt; conversions as in earlier versions.&lt;&#x2F;li&gt;
&lt;li&gt;Better Integration with Modern Frontend Tools: Tailwind 4.0 works more naturally with frameworks like React,
allowing dynamic updates like theme toggling with minimal configuration.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Here’s how we take advantage of these features to implement our theme toggle.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;setting-up-the-theme-in-tailwind-css-4-0&quot;&gt;Setting Up the Theme in Tailwind CSS 4.0&lt;&#x2F;h2&gt;
&lt;p&gt;In our project, we define theme variables directly in &lt;code&gt;src&#x2F;App.css&lt;&#x2F;code&gt; using the &lt;code&gt;@theme&lt;&#x2F;code&gt; directive. This eliminates the
need for extending Tailwind&#x27;s configuration in a separate file. I just chose the colors randomly because they only serve
as examples.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;src-app-css&quot;&gt;src&#x2F;App.css&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;css&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;@&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;tailwindcss&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;@&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;theme&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    --color-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;: initial;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Default theme light &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    --color-neutral-50:  oklch(0&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;147&lt;&#x2F;span&gt;&lt;span&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;004&lt;&#x2F;span&gt;&lt;span&gt;  49&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;250&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    --color-neutral-100: oklch(0&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;216&lt;&#x2F;span&gt;&lt;span&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;006&lt;&#x2F;span&gt;&lt;span&gt;  56&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;043&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    --color-neutral-200: oklch(0&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;268&lt;&#x2F;span&gt;&lt;span&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;007&lt;&#x2F;span&gt;&lt;span&gt;  34&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;298&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    --color-neutral-300: oklch(0&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;374&lt;&#x2F;span&gt;&lt;span&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;010&lt;&#x2F;span&gt;&lt;span&gt;  67&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;558&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    --color-neutral-400: oklch(0&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;444&lt;&#x2F;span&gt;&lt;span&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;011&lt;&#x2F;span&gt;&lt;span&gt;  73&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;639&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ... &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;@&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;layer&lt;&#x2F;span&gt;&lt;span&gt; base&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    [&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;data-theme&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;dark&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        --color-neutral-50&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-support z-function&quot;&gt;  oklch&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0.985&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0.001&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 106.423&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        --color-neutral-100&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-support z-function&quot;&gt; oklch&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0.970&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0.001&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 106.424&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        --color-neutral-200&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-support z-function&quot;&gt; oklch&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0.923&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0.003&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;  48.717&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        --color-neutral-300&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-support z-function&quot;&gt; oklch&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0.869&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0.005&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;  56.366&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        --color-neutral-400&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-support z-function&quot;&gt; oklch&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0.709&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0.010&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;  56.259&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        &#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ... &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name z-pseudo-class&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name z-pseudo-class&quot;&gt;root&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-support z-type z-property-name&quot;&gt;    background-color&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-support z-function&quot;&gt; var&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;--color-neutral-950&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The plan here is to set the &lt;code&gt;data-theme&lt;&#x2F;code&gt; attribute of the &lt;code&gt;&amp;lt;html&amp;gt;&lt;&#x2F;code&gt; element to &lt;code&gt;dark&lt;&#x2F;code&gt; when the dark mode is selected. If
the &lt;code&gt;light&lt;&#x2F;code&gt; mode is used, the attribute is set to &lt;code&gt;light&lt;&#x2F;code&gt;. Since we have two sets of colors in the CSS file, the default
set is selected when the attribute is absent or has another value than &lt;code&gt;dark&lt;&#x2F;code&gt;. If the attribute has the value &lt;code&gt;dark&lt;&#x2F;code&gt;,
then the alternative color set is used:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Light Theme: Default values for colors are defined in the &lt;code&gt;@theme&lt;&#x2F;code&gt; block.&lt;&#x2F;li&gt;
&lt;li&gt;Dark Theme: Dynamically overrides the light theme when the &lt;code&gt;data-theme=&quot;dark&quot;&lt;&#x2F;code&gt; attribute is present on the
&lt;code&gt;&amp;lt;html&amp;gt;&lt;&#x2F;code&gt; element.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This approach is declarative and keeps theme-related styling in one place. We can now use the colors &lt;code&gt;neutral-100&lt;&#x2F;code&gt;,
&lt;code&gt;primary-200&lt;&#x2F;code&gt;, &lt;code&gt;ok-300&lt;&#x2F;code&gt;, &lt;code&gt;warn-400&lt;&#x2F;code&gt;, or &lt;code&gt;fail-500&lt;&#x2F;code&gt; with any of the color prefixes, like &lt;code&gt;bg-&lt;&#x2F;code&gt;, &lt;code&gt;text-&lt;&#x2F;code&gt;, or
&lt;code&gt;border-&lt;&#x2F;code&gt;. Opacity is also built in, so we can use it like this: &lt;code&gt;text-primary-200&#x2F;50&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;implementing-the-theme-toggle-in-react&quot;&gt;Implementing the Theme Toggle in React&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;code&gt;src&#x2F;component&#x2F;card.jsx&lt;&#x2F;code&gt; file handles the dynamic toggling of the dark theme. Here’s a breakdown of how it works:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;src-component-card-jsx&quot;&gt;src&#x2F;component&#x2F;card.jsx&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;jsx&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; React&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; useLayoutEffect&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; useState&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; from&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;react&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; APPLICATION_NAME&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;color-theme-toggle&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Inline SVG so we can take advantage of currentColor (text-color)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; SvgImage&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parameter&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt; src&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parameter&quot;&gt; }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; svgContent&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; atob&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;src&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;split&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-definition z-tag z-begin&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt; dangerouslySetInnerHTML&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-embedded&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-meta z-embedded&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-meta z-embedded&quot;&gt; __html&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; svgContent&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-meta z-embedded&quot;&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-embedded&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-definition z-tag z-end&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; Card&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parameter&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt; card&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parameter&quot;&gt; }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; lightTheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;light&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; darkTheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;dark&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; getDataTheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;theme&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; theme&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; ===&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; darkTheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; ?&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; darkTheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; lightTheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; getToggledTheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;theme&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; theme&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; ===&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; darkTheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; ?&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; lightTheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; darkTheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; initialTheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; localStorage&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;getItem&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt;APPLICATION_NAME&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; lightTheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt;theme&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; setTheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; useState&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;initialTheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;  useLayoutEffect&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;    document&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;documentElement&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;setAttribute&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;data-theme&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; getDataTheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;theme&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;  }&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;theme&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; toggleTheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; newTheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; getToggledTheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;theme&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    setTheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;newTheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;    localStorage&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;setItem&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt;APPLICATION_NAME&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; getDataTheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;newTheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;  }&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; darkIcon&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; lightIcon&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; heading&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; text&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; card&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; icons&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt; dark&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; lightIcon&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt; light&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; darkIcon&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-definition z-tag z-begin&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt; className&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;flex min-h-screen min-w-full flex-col items-center justify-center&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-jsx z-children z-punctuation z-definition z-tag z-begin&quot;&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;article&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;        className&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;relative w-[80%] max-w-[500px] rounded-lg border border-neutral-500 bg-neutral-900 p-8 shadow-2xl text-neutral-300&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-jsx z-children z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-jsx z-children z-punctuation z-definition z-tag z-begin&quot;&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt; onClick&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-embedded&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;toggleTheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-embedded&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt; className&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;absolute top-0 right-0 mr-8 mt-8 cursor-pointer w-6 h-6&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-jsx z-children z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-jsx z-children z-punctuation z-definition z-tag z-begin&quot;&gt;          &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-class z-component&quot;&gt;SvgImage&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt; src&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-embedded&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;icons&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-meta z-embedded&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;theme&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-meta z-embedded&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-embedded&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-jsx z-children z-punctuation z-definition z-tag z-end&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-jsx z-children z-punctuation z-definition z-tag z-begin&quot;&gt;        &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-jsx z-children z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-jsx z-children z-punctuation z-definition z-tag z-begin&quot;&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;h1&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt; className&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;text-2xl font-bold text-primary-400&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-jsx z-children z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-embedded&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;heading&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-embedded&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-jsx z-children z-punctuation z-definition z-tag z-begin&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;h1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-jsx z-children z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-jsx z-children z-punctuation z-definition z-tag z-begin&quot;&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt; className&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; py-8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-jsx z-children z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-embedded&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;text&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-embedded&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-jsx z-children z-punctuation z-definition z-tag z-begin&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-jsx z-children z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-jsx z-children z-punctuation z-definition z-tag z-begin&quot;&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt; className&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-embedded&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;grid grid-cols-11 gap-[2px]&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-embedded&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-jsx z-children z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-embedded&quot;&gt;          {&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-meta z-embedded&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;neutral&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;primary&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;warn&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;fail&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-meta z-embedded&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;map&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-meta z-embedded&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-meta z-embedded&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;color&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt; colorIndex&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-meta z-embedded&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-meta z-embedded&quot;&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-meta z-embedded&quot;&gt;            [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;50&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;100&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;200&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;300&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;400&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;500&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;600&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;700&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;800&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;900&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;950&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-meta z-embedded&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;map&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-meta z-embedded&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-meta z-embedded&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;tone&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt; toneIndex&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-meta z-embedded&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-meta z-embedded&quot;&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-punctuation z-definition z-tag z-begin&quot;&gt;              &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt; key&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-embedded&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;key-&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-punctuation z-definition z-template-expression&quot;&gt;${&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;colorIndex&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-punctuation z-definition z-template-expression&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-punctuation z-definition z-template-expression&quot;&gt;${&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;toneIndex&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-punctuation z-definition z-template-expression&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-embedded&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt; className&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-embedded&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;bg-&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-punctuation z-definition z-template-expression&quot;&gt;${&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;color&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-punctuation z-definition z-template-expression&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-punctuation z-definition z-template-expression&quot;&gt;${&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;tone&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-punctuation z-definition z-template-expression&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; m-0 p-0 h-8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-embedded&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-punctuation z-definition z-tag z-begin&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-meta z-embedded&quot;&gt;            )&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-meta z-embedded&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-meta z-embedded&quot;&gt;          )&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-embedded z-expression z-meta z-embedded&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-embedded&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-jsx z-children z-punctuation z-definition z-tag z-begin&quot;&gt;        &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-jsx z-children z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-jsx z-children z-punctuation z-definition z-tag z-begin&quot;&gt;      &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;article&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-jsx z-children z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-definition z-tag z-begin&quot;&gt;    &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;  )&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; default&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; Card&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;initialize-theme-based-on-local-storage&quot;&gt;Initialize Theme Based on Local Storage&lt;&#x2F;h2&gt;
&lt;p&gt;When the component mounts, it checks &lt;code&gt;localStorage&lt;&#x2F;code&gt; for a saved theme:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;jsx&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; initialTheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; localStorage&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;getItem&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt;APPLICATION_NAME&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; lightTheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt;theme&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; setTheme&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; useState&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;initialTheme&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If no theme was saved, the light theme is used as the default.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;toggle-theme-dynamically&quot;&gt;Toggle Theme Dynamically&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;code&gt;toggleTheme&lt;&#x2F;code&gt; function toggles between light and dark themes:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;jsx&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; newTheme&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; getToggledTheme&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;theme&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;setTheme&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;newTheme&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;localStorage&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;setItem&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt;APPLICATION_NAME&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; getDataTheme&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;newTheme&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;data-theme&lt;&#x2F;code&gt; attribute is set for the &lt;code&gt;&amp;lt;html&amp;gt;&lt;&#x2F;code&gt; element.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;localStorage&lt;&#x2F;code&gt; is updated to persist the user&#x27;s preference.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;tailwind-css-4-0-vs-previous-versions&quot;&gt;Tailwind CSS 4.0 vs. previous versions&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;simpler-theming-with-theme&quot;&gt;Simpler Theming with @theme&lt;&#x2F;h3&gt;
&lt;p&gt;In Tailwind 3.4, you needed to extend &lt;code&gt;tailwind.config.js&lt;&#x2F;code&gt; with &lt;code&gt;extend&lt;&#x2F;code&gt; blocks to define custom properties and manually
manage theme variables. This separated theme logic from styles, making it harder to maintain.&lt;&#x2F;p&gt;
&lt;p&gt;Themes are defined directly in CSS in Tailwind 4.0, using the &lt;code&gt;@theme&lt;&#x2F;code&gt; directive. This keeps everything centralized and
declarative.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;automatic-opacity-handling&quot;&gt;Automatic Opacity Handling&lt;&#x2F;h3&gt;
&lt;p&gt;In Tailwind 3.4, you had to manually handle opacity with &lt;code&gt;rgb(var(--color-variable) &#x2F; &amp;lt;alpha-value&amp;gt;)&lt;&#x2F;code&gt;. This required
additional configuration for custom colors.&lt;&#x2F;p&gt;
&lt;p&gt;Opacity is automatically integrated into colors in Tailwind 4.0. For example, &lt;code&gt;text-primary-200&#x2F;50&lt;&#x2F;code&gt; adjusts the text
color&#x27;s opacity to 50% without requiring extra setup.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;seamless-integration-with-react&quot;&gt;Seamless Integration with React&lt;&#x2F;h3&gt;
&lt;p&gt;Tailwind 4.0&#x27;s improved theming and opacity handling simplifies React integration.
Dynamic updates, like toggling &lt;code&gt;data-theme&lt;&#x2F;code&gt;, feel natural and require minimal configuration.&lt;&#x2F;p&gt;
&lt;p&gt;Dark theme toggling in React applications with Tailwind CSS 4.0 is straightforward. With the &lt;code&gt;@theme&lt;&#x2F;code&gt; directive,
automatic opacity handling, and declarative CSS, it removes the boilerplate required in 3.4. By combining these features
with local storage, our implementation ensures a consistent and personalized user experience across sessions.&lt;&#x2F;p&gt;
&lt;p&gt;Tailwind CSS 4.0 is a clear step forward for developers, offering simplicity, flexibility, and modern tools to build
awesome, accessible web applications. If you’re still on an older version, it’s time to upgrade and experience the
difference! As of the date I&#x27;m writing this post, Tailwind CSS 4.0 is still in beta, but it already looks good and will
eventually become stable.&lt;&#x2F;p&gt;
&lt;p&gt;While I have used only two color sets for two different color themes here, you can extend this approach to support as
many themes as you like. Once the work of defining custom colors and using them is completed, there is no need to change
any of the Tailwind utility classes used in the React components anymore.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Is CSS a programming language?</title>
        <published>2024-11-29T00:00:00+00:00</published>
        <updated>2024-11-29T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/css-programming-language/"/>
        <id>https://weitzel.dev/blog/css-programming-language/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/css-programming-language/">&lt;p&gt;Whether CSS qualifies as a programming language has long been a topic of debate, particularly among
developers from different disciplines, such as frontend versus backend. To address this question, let’s
dissect it from several angles: definitional, functional, semantic, and pragmatic. By the end, I synthesize
these perspectives into a coherent conclusion.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m a backend developer specializing in building and maintaining backend services that integrate SQL databases and other APIs.
I long thought that CSS was &lt;strong&gt;not&lt;&#x2F;strong&gt; a programming language. But recently I have reconsidered this idea.
Mainly because I saw what &quot;Fluid Layout&quot; means and how e.g. functions like &lt;code&gt;clamp&lt;&#x2F;code&gt; and &lt;code&gt;minmax&lt;&#x2F;code&gt; can be used.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-defines-a-programming-language&quot;&gt;What Defines a Programming Language?&lt;&#x2F;h2&gt;
&lt;p&gt;To determine if CSS is a programming language, we must first clarify what constitutes one. Generally, programming
languages share the following characteristics:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Syntax and Structure: A defined set of rules and grammar for writing code.&lt;&#x2F;li&gt;
&lt;li&gt;Turing Completeness: The ability to represent a computation that can be performed by a Turing machine (e.g.
loops, conditionals, and variables).&lt;&#x2F;li&gt;
&lt;li&gt;Logic and Control Flow: Mechanisms to make decisions and repeat operations (e.g. &lt;code&gt;if&lt;&#x2F;code&gt; conditions, &lt;code&gt;for&lt;&#x2F;code&gt; loops).&lt;&#x2F;li&gt;
&lt;li&gt;Abstraction: The ability to encapsulate logic into reusable components (e.g. functions or classes).&lt;&#x2F;li&gt;
&lt;li&gt;Manipulation of State: The ability to change or operate on data values over time.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;css-and-these-characteristics&quot;&gt;CSS and These Characteristics:&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Syntax and Structure: CSS undeniably has a well-defined syntax for styling HTML elements. Selectors, properties,
and values form the core syntax.&lt;&#x2F;li&gt;
&lt;li&gt;Turing Completeness: CSS itself is not Turing complete because it lacks constructs like loops and conditionals in
its original form. However, modern CSS has introduced functions and features (like &lt;code&gt;calc()&lt;&#x2F;code&gt;, &lt;code&gt;clamp()&lt;&#x2F;code&gt;, &lt;code&gt;@media&lt;&#x2F;code&gt;, and
&lt;code&gt;@supports&lt;&#x2F;code&gt;) that allow for a more dynamic and conditional design, bringing it closer to computational logic.&lt;&#x2F;li&gt;
&lt;li&gt;Logic and Control Flow: CSS has conditional-like constructs in the form of media queries and feature queries
(&lt;code&gt;@media&lt;&#x2F;code&gt;, &lt;code&gt;@supports&lt;&#x2F;code&gt;), but these do not represent general-purpose logic flow.&lt;&#x2F;li&gt;
&lt;li&gt;Abstraction: CSS supports abstraction to some extent via reusable rules (e.g. variables with
&lt;code&gt;--custom-properties&lt;&#x2F;code&gt;, mixins in preprocessors like SASS, and shared class-based design patterns).&lt;&#x2F;li&gt;
&lt;li&gt;State Manipulation: CSS interacts with state indirectly (e.g. pseudo-classes like &lt;code&gt;:hover&lt;&#x2F;code&gt;, &lt;code&gt;:focus&lt;&#x2F;code&gt;, and
&lt;code&gt;:checked&lt;&#x2F;code&gt;), but it doesn’t directly manipulate values or states in the way imperative languages do.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Thus, CSS satisfies some but not all characteristics of traditional programming languages.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;css-as-a-declarative-language&quot;&gt;CSS as a Declarative Language&lt;&#x2F;h2&gt;
&lt;p&gt;CSS is generally categorized as a declarative language, meaning it describes what should happen rather than
providing explicit instructions on how to make it happen. For example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;css&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-support z-type z-property-name&quot;&gt;    color&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-constant&quot;&gt; red&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-support z-type z-property-name&quot;&gt;    display&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-constant&quot;&gt; flex&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, you declare that &lt;code&gt;div&lt;&#x2F;code&gt; elements should be red and laid out as flex containers. You don’t specify how the
browser engine achieves this result - this is abstracted away.&lt;&#x2F;p&gt;
&lt;p&gt;Declarative languages, including SQL are typically not considered programming
languages in the strictest sense. They lack imperative constructs like loops or explicit state management. However,
declarative languages are undeniably powerful tools in their respective domains.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;recent-enhancements-to-css&quot;&gt;Recent Enhancements to CSS&lt;&#x2F;h2&gt;
&lt;p&gt;Modern CSS introduces features that challenge its purely declarative nature:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;functions-e-g-clamp-calc-and-minmax&quot;&gt;Functions, e.g. clamp, calc, and minmax&lt;&#x2F;h3&gt;
&lt;p&gt;These functions allow you to perform calculations directly within the CSS, enabling dynamic behavior based on runtime
conditions:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;css&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;font-size&lt;&#x2F;span&gt;&lt;span&gt;: clamp(1rem&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; 2vw&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; 3rem&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;grid-template-columns&lt;&#x2F;span&gt;&lt;span&gt;: minmax(250px&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; 1fr&lt;&#x2F;span&gt;&lt;span&gt;) 2&lt;&#x2F;span&gt;&lt;span&gt;fr;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;These functions exhibit computational behavior, a hallmark of programming. However, they are limited to numerical
computations and cannot branch or loop.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;conditional-logic-e-g-media-and-supports&quot;&gt;Conditional Logic, e.g. @media and @supports&lt;&#x2F;h3&gt;
&lt;p&gt;Media queries &lt;code&gt;@media&lt;&#x2F;code&gt; and feature queries &lt;code&gt;@supports&lt;&#x2F;code&gt; provide conditional logic in CSS. An &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ishadeed.com&#x2F;article&#x2F;css-grid-masonry&#x2F;#grid-independent-option-4&quot;&gt;example&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;scss&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;section&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-support z-type z-property-name&quot;&gt;  display&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-constant&quot;&gt; grid&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-support z-type z-property-name&quot;&gt;  grid-template-columns&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-support z-function&quot;&gt; repeat&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-constant&quot;&gt;auto-fit&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-support z-function&quot;&gt; minmax&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;250&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;px&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;fr&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-support z-type z-property-name&quot;&gt;  gap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;rem&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  @&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;supports&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-support z-type z-property-name&quot;&gt;display&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; masonry&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-support z-type z-property-name&quot;&gt;    display&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; masonry&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-property-name&quot;&gt;    masonry-template-tracks&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-support z-function&quot;&gt; repeat&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-constant&quot;&gt;auto-fit&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-support z-function&quot;&gt; minmax&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;250&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;px&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;fr&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As you can see ...&lt;&#x2F;p&gt;
&lt;blockquote class=&quot;hippo&quot;&gt;
Whoa, whoa, whoa! Hold up, Code Captain! You just tossed out a CSS snippet like it’s a casual Tuesday, but let’s give
this masterpiece the attention it deserves, shall we?&lt;br&gt;
This isn’t just any grid - it’s a fancy-pants grid with a hidden agenda. Let’s unpack this brilliance, step by step!
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Yes, you&#x27;re absolutely right. We should spend some time with this thing!&lt;&#x2F;p&gt;
&lt;p&gt;Let’s break down this CSS step by step to understand what each line does, including the use of the &lt;code&gt;masonry&lt;&#x2F;code&gt; feature:&lt;&#x2F;p&gt;
&lt;h4 id=&quot;base-rules-for-the-section-element&quot;&gt;Base Rules for the section element&lt;&#x2F;h4&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;css&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;section&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-support z-type z-property-name&quot;&gt;  display&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-constant&quot;&gt; grid&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-support z-type z-property-name&quot;&gt;  grid-template-columns&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-support z-function&quot;&gt; repeat&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-constant&quot;&gt;auto-fit&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-support z-function&quot;&gt; minmax&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;250&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;px&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;fr&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-support z-type z-property-name&quot;&gt;  gap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;rem&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;display: grid;&lt;&#x2F;code&gt;
&lt;ul&gt;
&lt;li&gt;Sets the &lt;code&gt;.section&lt;&#x2F;code&gt; element to use CSS Grid for its layout.&lt;&#x2F;li&gt;
&lt;li&gt;CSS Grid is a powerful layout system that arranges content into rows and columns, allowing precise control over alignment and spacing.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;grid-template-columns: repeat(auto-fit, minmax(250px, 1fr))&lt;&#x2F;code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;repeat(auto-fit, ...)&lt;&#x2F;code&gt;:
&lt;ul&gt;
&lt;li&gt;Automatically determines the number of columns that can fit in the available space.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;auto-fit&lt;&#x2F;code&gt; ensures that grid items expand to fill the row even if there aren’t enough items to fill all columns.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;minmax(250px, 1fr)&lt;&#x2F;code&gt;:
&lt;ul&gt;
&lt;li&gt;Each column is at least &lt;code&gt;250px&lt;&#x2F;code&gt; wide (the minimum size) but can expand to fill available space (up to &lt;code&gt;1fr&lt;&#x2F;code&gt;), where &lt;code&gt;fr&lt;&#x2F;code&gt; stands for a fraction of the available free space.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This combination creates a responsive layout where the number of columns adjusts based on the container width, and columns are sized dynamically within the defined constraints.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;gap: 1rem&lt;&#x2F;code&gt;
&lt;ul&gt;
&lt;li&gt;Adds spacing of &lt;code&gt;1rem&lt;&#x2F;code&gt; between grid items in both rows and columns.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;masonry-specific-rules-inside-supports&quot;&gt;Masonry-Specific Rules Inside @supports&lt;&#x2F;h4&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;scss&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;@&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;supports&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-support z-type z-property-name&quot;&gt;display&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; masonry&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-support z-type z-property-name&quot;&gt;  display&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; masonry&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-property-name&quot;&gt;  masonry-template-tracks&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-support z-function&quot;&gt; repeat&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-constant&quot;&gt;auto-fit&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-support z-function&quot;&gt; minmax&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;250&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;px&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;fr&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;@supports (display: masonry) { ... }&lt;&#x2F;code&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;@supports&lt;&#x2F;code&gt; rule checks whether the browser supports the &lt;code&gt;masonry&lt;&#x2F;code&gt; value for the &lt;code&gt;display&lt;&#x2F;code&gt; property.&lt;&#x2F;li&gt;
&lt;li&gt;If &lt;code&gt;masonry&lt;&#x2F;code&gt; is supported, the rules inside the block are applied.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;display: masonry&lt;&#x2F;code&gt;
&lt;ul&gt;
&lt;li&gt;Sets the layout to &lt;code&gt;masonry&lt;&#x2F;code&gt;, a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;CSS&#x2F;CSS_grid_layout&#x2F;Masonry_layout#browser_compatibility&quot;&gt;Firefox and Safari feature&lt;&#x2F;a&gt; with some limitations at the time of writing.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;CSS&#x2F;CSS_grid_layout&#x2F;Masonry_layout&quot;&gt;Masonry layouts&lt;&#x2F;a&gt; arrange items in a staggered, vertical pattern, much like how Pinterest displays content.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;masonry-template-tracks: repeat(auto-fit, minmax(250px, 1fr))&lt;&#x2F;code&gt;
&lt;ul&gt;
&lt;li&gt;Defines how the masonry layout organizes its columns:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;repeat(auto-fit, ...)&lt;&#x2F;code&gt;: Similar to the grid layout, automatically determines the number of columns that can fit in the container.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;minmax(250px, 1fr)&lt;&#x2F;code&gt;: Ensures each column is at least &lt;code&gt;250px&lt;&#x2F;code&gt; wide but can expand proportionally to fill the remaining space (&lt;code&gt;1fr&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This rule customizes the behavior of the masonry layout to align with the grid’s column definitions, ensuring a consistent visual structure regardless of whether masonry is supported.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;summary-of-behavior&quot;&gt;Summary of Behavior&lt;&#x2F;h4&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Default Layout (Grid):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;By default, the &lt;code&gt;.section&lt;&#x2F;code&gt; uses CSS Grid.&lt;&#x2F;li&gt;
&lt;li&gt;The number of columns dynamically adjusts based on the available space, ensuring responsive behavior.&lt;&#x2F;li&gt;
&lt;li&gt;Items are laid out in a strict row-and-column structure with equal gaps (&lt;code&gt;1rem&lt;&#x2F;code&gt;) between them.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Enhanced Layout (Masonry):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;If the browser supports the &lt;code&gt;masonry&lt;&#x2F;code&gt; display value, the layout switches to a masonry-style layout.&lt;&#x2F;li&gt;
&lt;li&gt;Items are stacked vertically in staggered columns, but the column sizes are still defined using the same &lt;code&gt;minmax(250px, 1fr)&lt;&#x2F;code&gt; logic.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Fallback and Progressive Enhancement:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Browsers that do not support &lt;code&gt;masonry&lt;&#x2F;code&gt; fall back to the standard grid layout, ensuring the layout remains functional and visually appealing.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h4 id=&quot;key-advantages-of-this-code&quot;&gt;Key Advantages of This Code&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;Responsive Design: The use of &lt;code&gt;repeat(auto-fit, minmax(...))&lt;&#x2F;code&gt; makes the layout responsive to container width.&lt;&#x2F;li&gt;
&lt;li&gt;Progressive Enhancement: The &lt;code&gt;@supports&lt;&#x2F;code&gt; block ensures the enhanced masonry layout is only applied in browsers that support it, while maintaining compatibility with other browsers.&lt;&#x2F;li&gt;
&lt;li&gt;Visual Consistency: Both the grid and masonry layouts share the same column-sizing logic, minimizing discrepancies between supported and unsupported browsers.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This code demonstrates modern CSS practices for creating flexible, responsive, and progressively enhanced layouts.&lt;&#x2F;p&gt;
&lt;p&gt;Now, back to our main text.&lt;&#x2F;p&gt;
&lt;p&gt;These constructs resemble &lt;code&gt;if&lt;&#x2F;code&gt; statements but operate declaratively - they describe what to apply under certain
conditions, without actively controlling flow.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;pseudo-classes-and-states&quot;&gt;Pseudo-Classes and States&lt;&#x2F;h3&gt;
&lt;p&gt;CSS pseudo-classes like &lt;code&gt;:hover&lt;&#x2F;code&gt;, &lt;code&gt;:focus&lt;&#x2F;code&gt;, and &lt;code&gt;:nth-child()&lt;&#x2F;code&gt; allow for dynamic styles based on user interaction or
element position. While they can produce intricate designs, they don’t directly manipulate state or offer procedural
control flow.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;preprocessors-e-g-sass-less&quot;&gt;Preprocessors, e.g. SASS, LESS&lt;&#x2F;h3&gt;
&lt;p&gt;While not CSS itself, preprocessors extend CSS with imperative constructs like loops, variables, and functions:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;scss&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;@&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; $i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; from&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; through&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;  .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt;box-&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;#{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;$i&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-support z-type z-property-name&quot;&gt;    width&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; $i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 10&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;px&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This introduces procedural programming concepts but requires a compilation step before outputting standard CSS.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-case-for-css-as-a-programming-language&quot;&gt;The Case for CSS as a Programming Language&lt;&#x2F;h2&gt;
&lt;p&gt;If you reconsider the core purpose of CSS, you might argue it performs programming-like tasks. A programming language
does not necessarily need to be imperative or Turing complete to be considered one - it must simply provide mechanisms to
solve problems or express computations in its domain.&lt;&#x2F;p&gt;
&lt;p&gt;CSS increasingly enables developers to solve complex layout and styling problems programmatically:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The introduction of CSS Grid and Flexbox makes layout a computational exercise.&lt;&#x2F;li&gt;
&lt;li&gt;Functions like &lt;code&gt;clamp()&lt;&#x2F;code&gt; and &lt;code&gt;calc()&lt;&#x2F;code&gt; blur the lines between styling and computation.&lt;&#x2F;li&gt;
&lt;li&gt;The growing interactivity provided by pseudo-classes and conditional logic approaches stateful behavior.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;From this perspective, CSS can be seen as a domain-specific programming language for styling.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-pragmatic-perspective&quot;&gt;The Pragmatic Perspective&lt;&#x2F;h2&gt;
&lt;p&gt;Labels matter less than functionality. Even if CSS is not a &quot;programming language&quot; in the strictest sense, it has
evolved into a powerful, essential tool for web development. It operates in tandem with HTML and JavaScript, and modern
features make it more dynamic and computational than ever before.&lt;&#x2F;p&gt;
&lt;p&gt;For backend developers like myself, the growing sophistication of CSS feels closer to programming because its
features now demand a deeper understanding of computational logic. Terms like &quot;fluid layouts&quot; and functions like
&lt;code&gt;clamp()&lt;&#x2F;code&gt; require thought processes akin to solving problems with code.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;but-what-about-the-initial-question&quot;&gt;But What About the Initial Question?&lt;&#x2F;h2&gt;
&lt;p&gt;CSS is not traditionally classified as a programming language, as it lacks imperative control structures and state
manipulation. However, it shares several characteristics of domain-specific programming languages (e.g. SQL) and has
evolved to include computational and conditional capabilities.&lt;&#x2F;p&gt;
&lt;p&gt;If we loosen the definition of a programming language to include declarative and domain-specific tools, CSS could
qualify as a programming-adjacent language. Whether you call it a programming language or not, its modern
capabilities demand respect and computational thinking.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Intuition vs. mathematical facts</title>
        <published>2023-11-14T00:00:00+00:00</published>
        <updated>2023-11-14T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/perception-vs-mathematical-facts/"/>
        <id>https://weitzel.dev/blog/perception-vs-mathematical-facts/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/perception-vs-mathematical-facts/">&lt;p&gt;I will be discussing the effectiveness of tests for detecting infections.
Think of antigen tests for detecting COVID-19 infections.
Antigen tests are a rapid testing method used to detect specific proteins from the virus,
providing results within minutes.
Although they offer quick and scalable testing solutions,
their accuracy and reliability in mass screenings like those conducted in schools during the pandemic
may not be as clear-cut as one might assume.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;base-rates-and-conditional-probability&quot;&gt;Base rates and conditional probability&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s begin with some basics.
The &lt;em&gt;base rate&lt;&#x2F;em&gt; refers to the prevalence of a condition in a population before considering additional evidence,
which in our case is arbitrarily assumed to be a 0.5% infection rate as an example.
&lt;em&gt;Conditional probability&lt;&#x2F;em&gt; is the probability that an event occurs given that another event has already occurred,
which is crucial in understanding test results.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;sensitivity-and-specificity&quot;&gt;Sensitivity and specificity&lt;&#x2F;h1&gt;
&lt;p&gt;Sensitivity refers to the effectiveness of a test in accurately identifying individuals who have a specific disease.
For the test in question, its sensitivity is 97%.
This implies that out of 100 people who are infected, the test will correctly identify 97 as having the disease.
This 97% figure represents a conditional probability,
calculated under the presumption that the person being tested is indeed infected.
The mathematical expression for this is $p(\mathit{test positive} \mid \mathit{infected})$.&lt;&#x2F;p&gt;
&lt;p&gt;Specificity, on the other hand, tells us how well the test identifies those without the disease,
which stands at 95% for our tests.
This means if we have 100 non-infected individuals, 95 will correctly test negative.&lt;&#x2F;p&gt;
&lt;p&gt;Superficially, these numbers seem to indicate that results with this specific test are highly accurate.
I will prove this assumption wrong by using probability trees and Bayes&#x27; theorem to highlight the high potential for false positives.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;probability-tree-diagram&quot;&gt;Probability tree diagram&lt;&#x2F;h1&gt;
&lt;p&gt;Visualizing these concepts, a probability tree diagram would branch out,
first splitting the population into &lt;em&gt;infected&lt;&#x2F;em&gt; and &lt;em&gt;not infected&lt;&#x2F;em&gt;,
and then further into &lt;em&gt;test positive&lt;&#x2F;em&gt; and &lt;em&gt;test negative&lt;&#x2F;em&gt; for each group.
This helps us see the proportion of each outcome in a simple, visual form.&lt;&#x2F;p&gt;
&lt;pre class=&quot;mermaid&quot;&gt;
  
    %%{ init: {&#x27;theme&#x27;: &#x27;forest&#x27;} }%%
  
  flowchart TD
    A[Start] --&gt; |&quot;p(infected) = 0.5%&quot;| B(infected)
    A --&gt; |&quot;p(not infected) = 99.5%&quot;| C(not infected)
    B --&gt; |&quot;p(test positive | infected) = 97%&quot;| D[&quot;true positive (sensitivity)&quot;]
    B --&gt; |&quot;p(test negative | infected) = 3%&quot;| E[false negative]
    C --&gt; |&quot;p(test positive | not infected) = 5%&quot;| F[false positive]
    C --&gt; |&quot;p(test negative | not infected) = 95%&quot;| G[&quot;true negative (specificity)&quot;]
    D -.- |&quot;p(infected ∩ test positive)&quot;| H[0.485%]
    E -.- |&quot;p(infected ∩ test negative)&quot;| I[0.015%]
    F -.- |&quot;p(not infected ∩ test positive)&quot;| J[4.975%]
    G -.- |&quot;p(not infected ∩ test negative)&quot;| K[94.525%]

    style D fill:#b00,stroke:#000,stroke-width:2px,color:#fff
    style G fill:#0b0,stroke:#000,stroke-width:2px,color:#fff
&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;contingency-table&quot;&gt;Contingency table&lt;&#x2F;h1&gt;
&lt;p&gt;Moving on to the contingency table, we can organize our outcomes into four categories:
true positives, false positives, true negatives, and false negatives, with their respective probabilities.
Additionally, we sum up the rows and columns to get the total probabilities.
This table helps in understanding the distribution and frequency of each result type.&lt;&#x2F;p&gt;
&lt;p&gt;The generic form of the contingency table looks like this:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;$B$&lt;&#x2F;th&gt;&lt;th&gt;$\bar{B}$&lt;&#x2F;th&gt;&lt;th&gt;$total$&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;$A$&lt;&#x2F;td&gt;&lt;td&gt;$p(A \cap B)$&lt;&#x2F;td&gt;&lt;td&gt;$p(A \cap \bar{B})$&lt;&#x2F;td&gt;&lt;td&gt;$p(A)$&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;$\bar{A}$&lt;&#x2F;td&gt;&lt;td&gt;$p(\bar{A} \cap B)$&lt;&#x2F;td&gt;&lt;td&gt;$p(\bar{A} \cap \bar{B})$&lt;&#x2F;td&gt;&lt;td&gt;$p(\bar{A})$&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;$total$&lt;&#x2F;td&gt;&lt;td&gt;$p(B)$&lt;&#x2F;td&gt;&lt;td&gt;$p(\bar{B})$&lt;&#x2F;td&gt;&lt;td&gt;$1$&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;If we use the following substitutions and the four probabilities from the diagram above, we can construct our final contingency table:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;$A$ = &lt;em&gt;infected&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;$\bar{A}$ = &lt;em&gt;not infected&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;$B$ = &lt;em&gt;test positive&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;$\bar{B}$ = &lt;em&gt;test negative&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;test positive&lt;&#x2F;th&gt;&lt;th&gt;test negative&lt;&#x2F;th&gt;&lt;th&gt;total&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;infected&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;0.485%&lt;&#x2F;td&gt;&lt;td&gt;0.015%&lt;&#x2F;td&gt;&lt;td&gt;0.5%&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;not infected&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;4.975%&lt;&#x2F;td&gt;&lt;td&gt;94.525%&lt;&#x2F;td&gt;&lt;td&gt;99.5%&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;total&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;5.46%&lt;&#x2F;td&gt;&lt;td&gt;94.54%&lt;&#x2F;td&gt;&lt;td&gt;100%&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h1 id=&quot;reverse-tree-diagram&quot;&gt;Reverse tree diagram&lt;&#x2F;h1&gt;
&lt;p&gt;In the previous sections, we calculated the overall probabilities for getting a positive or negative test result.
Now, we&#x27;ll use these probabilities as starting points for our reverse tree diagram.
This diagram helps us understand the likelihood of someone being actually sick or not after getting a test result.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s how it works: we begin with the total percentage of positive and negative test results that we computed earlier.
Then, we use these percentages to figure out two things: how many of these results are likely to come from people
who are actually infected and how many are from those who are not.
This step helps us untangle the probabilities and see the real chances of being sick or not
after a positive or negative test.
It&#x27;s like backtracking from the test result to the actual condition of the person.&lt;&#x2F;p&gt;
&lt;pre class=&quot;mermaid&quot;&gt;
  
    %%{ init: {&#x27;theme&#x27;: &#x27;forest&#x27;} }%%
  
  flowchart TD
    A[Start] --&gt; |&quot;p(test positive) = 5.46%&quot;| B(positive)
    A --&gt; |&quot;p(test negative) = 94.54%&quot;| C(negative)
    B --&gt; |&quot;p(infected | test positive) = 8.883%&quot;| D[true positive]
    B --&gt; |&quot;p(not infected | test positive) = 91.117%&quot;| F[false positive]
    C --&gt; |&quot;p(infected | test negative) = 0.016%&quot;| E[false negative]
    C --&gt; |&quot;p(not infected | test negative) = 99.984%&quot;| G[true negative]
    D -.- |&quot;p(test positive ∩ infected)&quot;| H[0.485%]
    E -.- |&quot;p(test negative ∩ infected)&quot;| I[0.015%]
    F -.- |&quot;p(test positive ∩ not infected)&quot;| J[4.975%]
    G -.- |&quot;p(test negative ∩ not infected)&quot;| K[94.525%]

    style F fill:#b00,stroke:#000,stroke-width:2px,color:#fff
&lt;&#x2F;pre&gt;
&lt;p&gt;As you can see, from those who received a positive test result, only 8.883% are actually infected, but 91.117% are not.
&lt;strong&gt;That&#x27;s a lot of false positives.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;bayes-theorem-calculation&quot;&gt;Bayes&#x27; theorem calculation&lt;&#x2F;h1&gt;
&lt;p&gt;Now, to calculate the probability that an individual who tested positive is actually infected,
we use Bayes&#x27; theorem as an alternative.
You can skip the reverse tree diagram and calculate the probability of $p(\mathit{not infected} \mid \mathit{test positive})$ directly using the formula below.
The formula tells us to multiply the probability of testing positive when not infected by
the overall probability of being not infected, and divide it by the overall probability of testing positive.&lt;&#x2F;p&gt;
&lt;p&gt;$$p(\mathit{not infected} \mid \mathit{test positive}) = \frac{p(\mathit{test positive} \mid \mathit{not infected}) \cdot p(\mathit{not infected})}{p(\mathit{test positive})}$$&lt;&#x2F;p&gt;
&lt;p&gt;If we take the values from the first tree diagram and the table above, we get:&lt;&#x2F;p&gt;
&lt;p&gt;$$p(\mathit{not infected} \mid \mathit{test positive}) = \frac{0.05 \cdot 0.995}{0.0546} = 0.91117 = 91.117\%$$&lt;&#x2F;p&gt;
&lt;p&gt;The reverse tree diagram and the application of Bayes&#x27; theorem both lead to an interesting conclusion.
Despite high sensitivity and specificity in testing,
the probability of an individual not being infected after a positive test result can be surprisingly high.
This situation exemplifies the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Base_rate_fallacy&quot;&gt;&lt;em&gt;base rate fallacy&lt;&#x2F;em&gt;&lt;&#x2F;a&gt;,
a common error where the base rate (prevalence of disease)
is frequently ignored in the interpretation of diagnostic test results.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;societal-impact-and-public-health-policy-implications&quot;&gt;Societal impact and public health policy implications&lt;&#x2F;h1&gt;
&lt;p&gt;While antigen tests are useful, their effectiveness as a mass screening tool is brought into question
by the potential for high rates of false positives relative to the actual infection rate.
The implications of these statistical misunderstandings extend far beyond individual cases of misdiagnosis.
False positives on a large scale can lead to significant public health and economic consequences.
Unnecessary quarantines based on incorrect test results can strain public health resources,
disrupt educational and workplace environments, and contribute to public anxiety and mistrust in health systems.&lt;&#x2F;p&gt;
&lt;p&gt;Furthermore, the reliance on such tests without a proper understanding of their limitations can lead to complacency
in other crucial public health measures.
It underscores the importance of comprehensive public health strategies that incorporate multiple layers of testing,
tracing, and preventive measures.&lt;&#x2F;p&gt;
&lt;p&gt;In light of these findings, it&#x27;s crucial for policymakers and health authorities to be guided
not just by the apparent accuracy of these tests but also by an understanding of their limitations
in the context of prevailing infection rates.
This calls for a nuanced approach to mass screening, where antigen tests are used judiciously and
in combination with other diagnostic methods, like PCR tests, especially when initial test results are positive.&lt;&#x2F;p&gt;
&lt;p&gt;Educating the public about the nature of these tests and their interpretation is also vital.
It is essential to foster a broader understanding that a positive result in a low-prevalence setting
does not equate to a definitive diagnosis.
This awareness can play a significant role in managing public expectations and responses during health crises.&lt;&#x2F;p&gt;
&lt;p&gt;By addressing these issues, we can enhance the effectiveness of our public health response,
reduce unnecessary burdens on individuals and society, and build a more resilient healthcare system
capable of facing future challenges.&lt;&#x2F;p&gt;
&lt;p&gt;Relying on intuition and gut feeling is a double-edged sword.
Sometimes, it can be a powerful tool, but it can also lead to disastrous results.
If there are tools to double-check your intuition, by all means, use them.
Most of the time, they exist.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Diagrams with Mermaid</title>
        <published>2023-10-29T00:00:00+00:00</published>
        <updated>2023-10-29T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/mermaid-in-blog-post/"/>
        <id>https://weitzel.dev/blog/mermaid-in-blog-post/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/mermaid-in-blog-post/">&lt;h2 id=&quot;what-are-mermaid-diagrams&quot;&gt;What are Mermaid diagrams?&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mermaid.js.org&quot;&gt;Mermaid&lt;&#x2F;a&gt; is a syntax similar to Markdown where you can use text to describe and automatically generate diagrams.
With Mermaid, you can generate
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mermaid.js.org&#x2F;syntax&#x2F;flowchart.html&quot;&gt;Flow charts&lt;&#x2F;a&gt;,
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mermaid.js.org&#x2F;syntax&#x2F;classDiagram.html&quot;&gt;UML diagrams&lt;&#x2F;a&gt;,
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mermaid.js.org&#x2F;syntax&#x2F;pie.html&quot;&gt;Pie charts&lt;&#x2F;a&gt;,
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mermaid.js.org&#x2F;syntax&#x2F;gantt.html&quot;&gt;Gantt diagrams&lt;&#x2F;a&gt;,
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mermaid.js.org&#x2F;syntax&#x2F;entityRelationshipDiagram.html&quot;&gt;Entity Relationship diagrams&lt;&#x2F;a&gt;,
and more.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;an-entity-relationship-diagram-example&quot;&gt;An Entity Relationship diagram example&lt;&#x2F;h2&gt;
&lt;pre class=&quot;mermaid&quot;&gt;
  
    %%{ init: {&#x27;theme&#x27;: &#x27;forest&#x27;} }%%
  
  erDiagram
    CUSTOMER ||--o{ ORDER : places
    ORDER ||--|{ LINEITEM : contains
    PRODUCT ||--o{ LINEITEM : is_listed_in
    CUSTOMER {
        string Name
        string Email
        string Address
    }
    PRODUCT {
        string ProductName
        float Price
    }
    ORDER {
        date DateOrdered
        string Status
    }
    LINEITEM {
        int Quantity
    }
&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;using-mermaid-in-your-blog-post&quot;&gt;Using Mermaid in your blog post&lt;&#x2F;h2&gt;
&lt;p&gt;The diagram shortcode allows you to easily embed Mermaid diagrams in your blog posts, with an option to configure its appearance.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;basic-usage&quot;&gt;Basic Usage&lt;&#x2F;h3&gt;
&lt;p&gt;To use the shortcode in your blog post, you would use the following format:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; diagram&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; %&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;Your&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; Mermaid&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; diagram&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; code&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; end&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; %&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Replace &lt;em&gt;Your Mermaid diagram code here&lt;&#x2F;em&gt; with your actual Mermaid diagram code.&lt;&#x2F;p&gt;
&lt;p&gt;To load the necessary JavaScript to render the Mermaid diagram, you need to enable it in the front matter of your blog post by setting the value for &lt;code&gt;extra.diagram&lt;&#x2F;code&gt; to &lt;code&gt;true&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+++&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;extra&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;diagram&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+++&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;configuring-the-appearance&quot;&gt;Configuring the Appearance&lt;&#x2F;h3&gt;
&lt;p&gt;The shortcode supports an optional &lt;code&gt;init&lt;&#x2F;code&gt; parameter that allows you to specify configuration options for Mermaid,
particularly changing the appearance of the diagrams through the theme.&lt;&#x2F;p&gt;
&lt;p&gt;For example, to apply the &lt;code&gt;forest&lt;&#x2F;code&gt; theme:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; diagram&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;init&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&amp;#39;theme&amp;#39;: &amp;#39;forest&amp;#39;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; %&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;Your&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; Mermaid&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; diagram&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; code&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; end&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; %&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;providing-init-configuration&quot;&gt;Providing init Configuration&lt;&#x2F;h3&gt;
&lt;p&gt;When using the &lt;code&gt;init&lt;&#x2F;code&gt; parameter, the configuration should be a string wrapped in double quotes.
Inside this string, use single quotes for keys and values.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s a more advanced example with multiple configuration options:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; diagram&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;init&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&amp;#39;theme&amp;#39;: &amp;#39;forest&amp;#39;, &amp;#39;themeVariables&amp;#39;: {&amp;#39;primaryColor&amp;#39;: &amp;#39;#FF0000&amp;#39;}}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; %&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;Your&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; Mermaid&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; diagram&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; code&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; end&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; %&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In this example, we&#x27;re using the &lt;code&gt;forest&lt;&#x2F;code&gt; theme and changing the primary color to red (&lt;code&gt;#FF0000&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;&#x2F;strong&gt;: Ensure that you use single quotes inside the double quotes for the configuration to work correctly.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;putting-it-all-together&quot;&gt;Putting it all together&lt;&#x2F;h3&gt;
&lt;p&gt;Use the shortcode by enclosing your Mermaid diagram code with it.
To change the look of the Mermaid theme, provide values for the &lt;code&gt;init&lt;&#x2F;code&gt; parameter.
Always enclose the &lt;code&gt;init&lt;&#x2F;code&gt; value with double quotes, and use single quotes inside the configuration string.
With this shortcode in place, integrating and customizing Mermaid diagrams in your blog posts becomes easy.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;explaining-mermaid-diagram-code&quot;&gt;Explaining Mermaid diagram code&lt;&#x2F;h2&gt;
&lt;p&gt;Here is how the diagram rendered above is embedded in this blog post as a code block.
Because it is the same code as the diagram above, extra care has to be taken to prevent Mermaid from rendering it as a diagram.
Use Zola’s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;documentation&#x2F;content&#x2F;shortcodes&#x2F;#shortcodes-without-body&quot;&gt;ignored shortcode syntax&lt;&#x2F;a&gt; in the code block, so the code stays visible but is not executed.
For example, use &lt;code&gt;{%&#x2F;*&lt;&#x2F;code&gt; for displaying &lt;code&gt;{%&lt;&#x2F;code&gt;, and &lt;code&gt;*&#x2F;%}&lt;&#x2F;code&gt; for displaying &lt;code&gt;%}&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; diagram&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;init&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&amp;#39;theme&amp;#39;: &amp;#39;forest&amp;#39;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; %&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt;    CUSTOMER&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;--&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; ORDER&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; places&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt;    ORDER&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;--&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; LINEITEM&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; contains&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt;    PRODUCT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;--&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; LINEITEM&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; is_listed_in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt;    CUSTOMER&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;        string&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; Name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;        string&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; Email&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;        string&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; Address&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt;    PRODUCT&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;        string&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; ProductName&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;        float&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; Price&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt;    ORDER&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;        date&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; DateOrdered&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;        string&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; Status&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt;    LINEITEM&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;        int&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; Quantity&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; end&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; %&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Internal rate of return calculation</title>
        <published>2023-07-29T00:00:00+00:00</published>
        <updated>2023-07-29T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/calculating-internal-interest-rate/"/>
        <id>https://weitzel.dev/blog/calculating-internal-interest-rate/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/calculating-internal-interest-rate/">&lt;p&gt;The internal rate of return (IRR) is a potent financial measure used in financial analysis, accounting, and portfolio management to gauge the profitability of investments.
It&#x27;s like the heartbeat of an investment - an indicator of health, the higher it is, the better the investment.
This powerful tool can help investors compare different investment options, assisting in making informed decisions about where to allocate their capital.
Especially when cash flows are irregular, as often is the case in real-world scenarios, IRR becomes invaluable.
This article will first explain the concept and calculations behind IRR and then demonstrate how to implement an IRR algorithm in Rust.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;irr-vs-xirr-terminology&quot;&gt;IRR vs. XIRR terminology&lt;&#x2F;h2&gt;
&lt;p&gt;The IRR is the rate of return that makes the net present value (NPV) of all cash flows (both positive and negative) from a particular investment equal to zero.
It&#x27;s sometimes used for cash flows at regular, usually annual, intervals.
I will not make this assumption in this article.
While Microsoft uses the name XIRR for its Excel function, I will use the term IRR throughout this article, even though the cash flows do not occur at regular intervals.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;example-data-and-validation&quot;&gt;Example data and validation&lt;&#x2F;h2&gt;
&lt;p&gt;A crucial part of implementing a financial algorithm like IRR is validation. That is, making sure that your algorithm is producing correct and expected results.
One effective way to validate your implementation is by comparing its outputs to those of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;support.microsoft.com&#x2F;en-gb&#x2F;office&#x2F;xirr-function-de1242ec-6477-445b-b11b-a303ad9adc9d&quot;&gt;Microsoft Excel&#x27;s XIRR function&lt;&#x2F;a&gt;.
I will use the data from the Excel example.
Using Excel&#x27;s XIRR function to compute the internal rate of return for this specific data set yields a result of $37.34\%$.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: right&quot;&gt;$\textbf{i}$&lt;&#x2F;th&gt;&lt;th&gt;ISO Date $\textbf{d}$&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Years since first cash flow $\textbf{y}$&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Payment $\textbf{p}$&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;1&lt;&#x2F;td&gt;&lt;td&gt;2008-01-01&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;0.0000&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;-10,000&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;2&lt;&#x2F;td&gt;&lt;td&gt;2008-03-01&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;0.1644&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;2,750&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;3&lt;&#x2F;td&gt;&lt;td&gt;2008-10-30&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;0.8301&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;4,250&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;4&lt;&#x2F;td&gt;&lt;td&gt;2009-02-15&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.1260&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;3,250&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;5&lt;&#x2F;td&gt;&lt;td&gt;2009-04-01&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.2493&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;2,750&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;how-irr-works&quot;&gt;How IRR works&lt;&#x2F;h2&gt;
&lt;p&gt;The IRR is calculated by finding the rate of return that would make the net present value (NPV) of an investment equal to zero.
The NPV is the sum of the present values of all future cash flows from an investment.
The derivative of the NPV is used to find the IRR.
The derivative of the NPV is the rate of change of the NPV with respect to the interest rate.&lt;&#x2F;p&gt;
&lt;p&gt;The IRR algorithm is an instance of the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Newton%27s_method&quot;&gt;Newton-Raphson method&lt;&#x2F;a&gt;,
which is a root-finding algorithm that produces successively better approximations to the roots (or zeroes) of a real-valued function.
To calculate the IRR, you need an array with pairs of data: one is the date of a cash flow, and the other is its payment amount.
You also need an initial guess for the IRR rate, which is often set as $10\%$ or $0.1$.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s the general process of the algorithm:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Compute the net present value (NPV)&lt;&#x2F;strong&gt;: The NPV is calculated by summing the present values of the individual cash flows.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Compute the derivative of the NPV&lt;&#x2F;strong&gt;: The derivative of the NPV with respect to the rate is created by differentiating the NPV formula and summing these values.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Update the guess&lt;&#x2F;strong&gt;: The next guess for the rate is calculated by subtracting the ratio of the NPV to its derivative from the current guess.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Iterate until convergence&lt;&#x2F;strong&gt;: These steps are repeated until the change in guesses is below a certain tolerance or until a maximum number of iterations is reached.
At this point, the guess for the rate is considered to be the IRR.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;compute-the-net-present-value-npv&quot;&gt;Compute the net present value (NPV)&lt;&#x2F;h2&gt;
&lt;p&gt;Here, $y_i$ represents the number of years that have passed since the first cash flow,
calculated as the difference in days between the date of the $i$-th cash flow $d_i$ and the date of the first cash flow $d_1$,
divided by 365 (days in one year).
I have pre-calculated it in the table above:&lt;&#x2F;p&gt;
&lt;p&gt;$$y_i = \frac{d_i - d_1}{365}$$&lt;&#x2F;p&gt;
&lt;p&gt;The NPV is the sum of all payments, where the correct interest rate $irr$ is applied.
Its value is 0 after all transactions have been concluded:&lt;&#x2F;p&gt;
&lt;p&gt;$$\mathit{NPV} = \sum_{i = 1}^{m} \frac{p_i}{(1 + irr)^{y_i}}$$&lt;&#x2F;p&gt;
&lt;p&gt;When you &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.wolframalpha.com&#x2F;input?i=plot+-10000*%281%2F%281+%2B+x%29%5E%280.0000%29%29+%2B+2750*%281%2F%281+%2B+x%29%5E%280.1644%29%29+%2B+4250*%281%2F%281+%2B+x%29%5E%280.8301%29%29+%2B+3250*%281%2F%281+%2B+x%29%5E%281.1260%29%29+%2B+2750*%281%2F%281+%2B+x%29%5E%281.2493%29%29+from+x%3D-0.1+to+0.9&quot;&gt;plot&lt;&#x2F;a&gt; the NPV function as a function of $irr$,
you are essentially varying the interest rate and observing how it affects the NPV.
Here&#x27;s what you see on the graph below, which plots the NPV as a function of the rate with the values from the table above:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;X-axis&lt;&#x2F;strong&gt;: The x-axis represents the interest rate $irr$.
It typically ranges from $0\%$ to a reasonable upper limit, depending on the context of your problem.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Y-axis&lt;&#x2F;strong&gt;: The y-axis represents the net present value NPV.
It&#x27;s the cumulative sum of the discounted cash flows according to the given formula.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Shape of the curve&lt;&#x2F;strong&gt;: The curve of the NPV function will generally be downward-sloping.
This is because as you increase the interest rate $irr$, the present value of future cash flows decreases.
Higher interest rates mean that future cash flows are being discounted more heavily, which reduces their present value.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Break-even point&lt;&#x2F;strong&gt;: There will be a point on the graph where the NPV curve intersects the x-axis.
It&#x27;s where our $irr$ satisfies the condition $\mathit{NPV} = 0$.
For our data, it is somewhere between $0.35$ and $0.40$, or $35\%$ and $40\%$.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;figure class=&quot;mt-4&quot;&gt;&lt;span class=&quot;light-dark-image inline-block&quot;&gt;
      &lt;img class=&quot;block image-shortcode&quot; src=&quot;https:&#x2F;&#x2F;weitzel.dev&#x2F;blog&#x2F;calculating-internal-interest-rate&#x2F;resources&#x2F;media&#x2F;irr-npv-function-light.webp&quot; alt=&quot;Plot of the NPV as a function of the rate with the values from the table&quot; width=&quot;560&quot; height=&quot;360&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
      &lt;img class=&quot;block image-shortcode&quot; src=&quot;https:&#x2F;&#x2F;weitzel.dev&#x2F;blog&#x2F;calculating-internal-interest-rate&#x2F;resources&#x2F;media&#x2F;irr-npv-function-dark.webp&quot; alt=&quot;Plot of the NPV as a function of the rate with the values from the table&quot; width=&quot;560&quot; height=&quot;360&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
    &lt;&#x2F;span&gt;
    &lt;figcaption class=&quot;italic&quot;&gt;Downward-sloping NPV curve&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;The above formula is a sum of function terms.
Applying the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Superposition_principle&quot;&gt;superposition principle&lt;&#x2F;a&gt;,
we can split the sum into individual function terms, which look all the same.
For each cash flow, we have a function term, which is the present value of the cash flow.
The important part is that we can apply this principle to the NPV function &lt;strong&gt;and&lt;&#x2F;strong&gt; the derivative of the NPV function.&lt;&#x2F;p&gt;
&lt;p&gt;With $irr$ written as $x$, each function term looks like this, where $p_i$ and $y_i$ are just constants.
$f_i(x)$ represents the NPV for a single cash flow, the $i$-th one:&lt;&#x2F;p&gt;
&lt;p&gt;$$f_i(x) = \frac{p_i}{(1 + x)^{y_i}}$$&lt;&#x2F;p&gt;
&lt;p&gt;The amount $p_i$ is discounted in the NPV calculation to reflect the time value of money. Here&#x27;s an explanation for why that&#x27;s done:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Time value of money&lt;&#x2F;strong&gt;: Money available today is worth more than the same amount in the future because of its potential earning capacity.
This core principle of finance holds that, provided money can earn interest, any amount of money is worth more the sooner it is received.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Discounting future cash flows&lt;&#x2F;strong&gt;: In the context of the internal rate of return (IRR) and net present value (NPV), this principle is applied to future cash flows.
The $p_i$ represents a payment (cash flow) at some future date. To compare this future value to present values,
it needs to be discounted back to its value in today&#x27;s terms.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;The discount factor&lt;&#x2F;strong&gt;: The expression $\frac{1}{(1 + x)^{y_i}}$ serves as a discount factor, where $x$ is the internal rate of return, and $y_i$ is the number of years that have passed since the first cash flow.
This factor is derived from the formula for compounding interest in reverse (discounting rather than compounding).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Sum of discounted payments&lt;&#x2F;strong&gt;: The NPV is the sum of these discounted payments. By discounting each future cash flow back to its present value,
the NPV provides a consistent basis for comparing the value of cash flows across different time periods.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Understanding the equation&lt;&#x2F;strong&gt;: The equation $f_i(x) = \frac{p_i}{(1 + x)^{y_i}}$ represents the present value of the $i$-th cash flow.
It shows how each cash flow is discounted back to present value terms using the discount factor.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Discounting the $p_i$ in the NPV calculation allows for a proper comparison of cash flows across different time periods,
taking into account the time value of money and the specific internal rate of return (IRR) required from the investment.
It ensures that future cash flows are appropriately weighed against the potential earning capacity of money in the present.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;but-what-happens-if&quot;&gt;But what happens if ...&lt;&#x2F;h3&gt;
&lt;p&gt;The expression $(1 + x)^{y_i}$ can become a problem if $x &amp;lt; -1$ (less than $-100\%$), because raising a negative number to a non-integer power will result in a complex number.
Within the realm of real numbers, this operation is undefined.
For example, consider a case where $x = -1.1$ and $y_i$ is a floating point number like $0.4$.
Then, $(1 + x)$ will be negative, and raising it to the $y_i$ power &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.wolframalpha.com&#x2F;input?i=%281+-+1.1%29%5E%280.4%29&quot;&gt;produces a complex value&lt;&#x2F;a&gt;:
${(1 - 1.1)}^{0.4} \approx 0.12 + 0.38 i$&lt;&#x2F;p&gt;
&lt;p&gt;In the context of finance and the calculation of IRR, it doesn&#x27;t make sense to have complex numbers as they don&#x27;t have a practical interpretation in terms of cash flows or discount rates.
Therefore, you would typically ensure that the rate $x$ stays within the range where the calculation remains within the realm of real numbers.
If you&#x27;re working with cash flows and discount rates, you may want to either avoid or handle situations where $x &amp;lt; -1$ by constraining the value of $x$ within a reasonable range or taking some other specific action if $x$ falls outside that range.&lt;&#x2F;p&gt;
&lt;p&gt;In practice, it&#x27;s rare that you would come across this scenario.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;compute-the-derivative-of-the-npv&quot;&gt;Compute the derivative of the NPV&lt;&#x2F;h2&gt;
&lt;p&gt;We can now apply the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.wolframalpha.com&#x2F;input?i=derivative+of+a+%2F+%28%281+%2B+x%29%5Eb%29&quot;&gt;basic differentiation rules&lt;&#x2F;a&gt; to get the derivative of $f_i(x)$.
It represents the derivative of the NPV for a single cash flow, also the $i$-th one:&lt;&#x2F;p&gt;
&lt;p&gt;$$f_i^\prime(x) = \frac{-y_i \cdot p_i}{(1 + x)^{y_i + 1}}$$&lt;&#x2F;p&gt;
&lt;h2 id=&quot;update-the-guess&quot;&gt;Update the guess&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Newton%27s_method&quot;&gt;Newton-Raphson method&lt;&#x2F;a&gt; is an iterative process used to locate the roots of a differentiable function, i.e. a solution for $x$ where $f(x) = 0$.
The method begins with an initial estimate $x_n$, which is then refined into a more accurate guess, $x_{n+1}$.
This stage is where the NPV and its derivative come into play.
Instead of solely employing $f_i(x_n)$ and $f_i^\prime(x_n)$ for a single cash flow, we incorporate all the cash flows by adding up the NPV terms and derivative terms respectively:&lt;&#x2F;p&gt;
&lt;p&gt;$$x_{n+1} = x_{n} - \frac{\sum_{i = 1}^{m} f_i(x_n)}{\sum_{i = 1}^{m} f_i^\prime(x_n)} $$&lt;&#x2F;p&gt;
&lt;h2 id=&quot;iterate-until-convergence&quot;&gt;Iterate until convergence&lt;&#x2F;h2&gt;
&lt;p&gt;Instead of improving the result indefinitely, you stop when the difference between $x_n$ and $x_{n+1}$ is smaller than or equal to a given $\epsilon$, i.e. $\left| x_n - x_{n+1} \right| \le \epsilon$.
It&#x27;s usually a tiny number, like $0.000001$ ($1.0 e^{-6}$).
This is the value used in Microsoft Excel&#x27;s XIRR function.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s also worth noting that despite using the exact derivative, the IRR algorithm is still an approximation method.
It may not always converge to a solution, especially for cash flow series that have multiple changes in sign.
In these cases, it may be necessary to provide a good initial guess for the rate or to use a different method to compute the internal rate of return.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;implementation-in-rust&quot;&gt;Implementation in Rust&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s move towards translating our theoretical understanding into a concrete implementation using Rust.
We&#x27;ll focus on implementing the IRR calculation algorithm by applying the findings and formulas mentioned in the previous sections.
The final output should be close to Excel&#x27;s XIRR function result within an acceptable tolerance range.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; We use the chrono crate for date handling: https:&#x2F;&#x2F;docs.rs&#x2F;chrono&#x2F;latest&#x2F;chrono&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; chrono&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;prelude&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Function to calculate the number of days between two dates&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; days_between&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;start_date&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; NaiveDate&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; end_date&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; NaiveDate&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; i64&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Calculate the duration between the two dates&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; end_date&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;signed_duration_since&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;start_date&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Return the duration in days&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;    duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;num_days&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Main function to calculate the internal rate of return&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; calculate_irr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;transactions&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;f64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; f64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; initial_guess&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; f64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; f64&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Start with initial guess for the IRR&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; initial_guess&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt; MAX_TRIES&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 100&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt; EPSILON&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; f64&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Loop until a maximum number of iterations is reached&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;..&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;MAX_TRIES&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Calculate NPV and its derivative for each cash flow and sum them up&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;fx&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; dfx&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; transactions&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;years&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; amount&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;                let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; fx&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; amount&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;1_&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;f64&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;powf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;years&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;                  &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; NPV of the cash flow&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;                let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; dfx&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;years&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; amount&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;1_&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;f64&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;powf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;years&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Derivative of NPV&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;fx&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; dfx&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;                                                    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Return both values for a single cash flow&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;            &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Sum up all NPVs and derivatives for all cash flows (reduce to a tuple of two sums)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;fold&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0_&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;f64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0_&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;f64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;fx_acc&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; dfx_acc&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;fx&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; dfx&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;fx_acc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; fx&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; dfx_acc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; dfx&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Calculate the new guess&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; new_x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; fx&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; dfx&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Calculate the difference between the new and the old guess&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; epsilon&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;new_x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;abs&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; If the difference is smaller than or equal to the tolerance, we are done&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; epsilon&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;lt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt; EPSILON&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Continue the loop with the new guess&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;        x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; new_x&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Return a non-number if the algorithm didn&amp;#39;t converge (see &amp;quot;Iterate until convergence&amp;quot; in article)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    f64&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;NAN&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Define the main function and our example transactions&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Example from Microsoft Excel documentation:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; https:&#x2F;&#x2F;support.microsoft.com&#x2F;en-gb&#x2F;office&#x2F;xirr-function-de1242ec-6477-445b-b11b-a303ad9adc9d&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; The internal rate of return is 0.373362535 or 37.34%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; cashflows&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        (&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;NaiveDate&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from_ymd_opt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;2008&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;  1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;  1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;10_000&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;00&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        (&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;NaiveDate&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from_ymd_opt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;2008&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;  3&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;  1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;   2_750&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;00&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        (&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;NaiveDate&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from_ymd_opt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;2008&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 10&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 30&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;   4_250&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;00&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        (&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;NaiveDate&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from_ymd_opt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;2009&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;  2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 15&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;   3_250&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;00&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        (&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;NaiveDate&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from_ymd_opt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;2009&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;  4&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;  1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;   2_750&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;00&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ]&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Pre-calculate the years since first cash flow for each cash flow&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; transactions&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;f64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; f64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; cashflows&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;date&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; amount&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;days_between&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;cashflows&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;date&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; as&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; f64&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 365&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;amount&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Call our IRR calculation function and print the result&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Expected result is 37.34%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;IRR with Newton-Raphson: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:.2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; calculate_irr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;transactions&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 100&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;calculate_irr&lt;&#x2F;code&gt; function is where the heart of our IRR calculation lives.
It starts by defining the initial guess for the IRR, then enters a loop that calculates the new guess, checks for convergence, and continues the loop if not converged.
Finally, if the algorithm fails to converge, it returns a non-number.
The main function uses an example transaction set and calls our &lt;code&gt;calculate_irr&lt;&#x2F;code&gt; function.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bonus-implementation-in-javascript&quot;&gt;Bonus: implementation in JavaScript&lt;&#x2F;h2&gt;
&lt;p&gt;JavaScript runs natively in all modern browsers and is the &lt;em&gt;lingua franca&lt;&#x2F;em&gt; of the web.
By translating the Rust code into JavaScript, the IRR calculation will be easily usable on virtually any device, regardless of operating system or hardware.
This way, it should be possible to use it in a web application or even in a mobile app using a framework like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;reactnative.dev&quot;&gt;React Native&lt;&#x2F;a&gt;.
Maybe you want to write a financial app that runs on iOS, Android, and the web?&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Function to calculate the number of days between two dates&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt;function&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; daysBetween&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;start&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt; end&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; millisecondsPerDay&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1000&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 60&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 60&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 24&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; millisBetween&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; end&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;getTime&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; start&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;getTime&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; millisBetween&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; millisecondsPerDay&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Main function to calculate the internal rate of return&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt;function&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; calculateIRR&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;transactions&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt; initialGuess&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;  &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Start with initial guess for the IRR&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; initialGuess&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; MAX_TRIES&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 100&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; EPSILON&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0e-6&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;  &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Loop until a maximum number of iterations is reached&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  for&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; tries&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; tries&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; MAX_TRIES&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; tries&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Calculate NPV and its derivative for each cash flow and sum them up&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; fxs&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; dfxs&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; transactions&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;      .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;map&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;tx&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;        const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; fx&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; tx&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;amount&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; tx&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;years&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;                      &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; NPV of the cash flow&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;        const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; dfx&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;tx&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;years&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; tx&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;amount&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;tx&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;years&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Derivative of NPV&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; fx&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; dfx&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;                                                  &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Return both values for a single cash flow&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;      }&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;      &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Sum up all NPVs and derivatives for all cash flows (reduce to an object with two sums)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;      .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;reduce&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;acc&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt; obj&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt; fxs&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; acc&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;fxs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; obj&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;fx&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt; dfxs&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; acc&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;dfxs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; obj&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;dfx&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt; fxs&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt; dfxs&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Calculate the new guess&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; xNew&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; fxs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; dfxs&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Calculate the difference between the new and the old guess&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; epsilon&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; Math&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;abs&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;xNew&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; If the difference is smaller than or equal to the tolerance, we are done&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;epsilon&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;lt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; EPSILON&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;      return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Continue the loop with the new guess&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;    x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; xNew&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;  &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Return a non-number if the algorithm didn&amp;#39;t converge&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-language&quot;&gt; NaN&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Example from Microsoft Excel documentation:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; https:&#x2F;&#x2F;support.microsoft.com&#x2F;en-gb&#x2F;office&#x2F;xirr-function-de1242ec-6477-445b-b11b-a303ad9adc9d&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; The internal rate of return is 0.373362535 or 37.34%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; cashflows&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt; date&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; new&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; Date&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2008-01-01&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt; amount&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;10000&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;00&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt; date&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; new&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; Date&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2008-03-01&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt; amount&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;   2750&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;00&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt; date&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; new&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; Date&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2008-10-30&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt; amount&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;   4250&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;00&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt; date&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; new&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; Date&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2009-02-15&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt; amount&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;   3250&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;00&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt; date&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; new&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; Date&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2009-04-01&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt; amount&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;   2750&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;00&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Pre-calculate the years since first cash flow for each cash flow&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; transactions&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; cashflows&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor&quot;&gt;  .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;cf&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt; years&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; daysBetween&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;cashflows&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;date&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; cf&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;date&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 365&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt; amount&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; cf&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;amount&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Call our IRR calculation function and print the result&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Expected result is 37.34%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;console&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;IRR with Newton-Raphson: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-punctuation z-definition z-template-expression&quot;&gt;${&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-meta z-embedded&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;calculateIRR&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-meta z-embedded&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;transactions&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-meta z-embedded&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 100&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-meta z-embedded&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;toFixed&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-meta z-embedded&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-meta z-embedded&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-punctuation z-definition z-template-expression&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;The internal rate of return (IRR) is an instrumental financial measure that helps investors compare and decide between different investment opportunities.
Calculating it can get complex due to irregular cash flows, making a detailed understanding of the underlying algorithm crucial.
This article dived into the mathematics behind IRR calculation and provided a concrete implementation using the Rust programming language.
Remember, IRR is not just a number but an insight into the potential of an investment, assisting you in making informed financial decisions.&lt;&#x2F;p&gt;
&lt;p&gt;If you have any questions, need further clarification, or want to give feedback: please let me know.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Structured data in Hugo templates</title>
        <published>2022-08-06T00:00:00+00:00</published>
        <updated>2022-08-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/hugo-structured-data/"/>
        <id>https://weitzel.dev/blog/hugo-structured-data/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/hugo-structured-data/">&lt;p&gt;Within a website, structured data is used to help search engines understand the context of that information better.
It&#x27;s organized and tagged with specific groups of text.
You can find a good introduction in the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developers.google.com&#x2F;search&#x2F;docs&#x2F;advanced&#x2F;structured-data&#x2F;intro-structured-data&quot;&gt;Google&#x27;s Search Central documentation&lt;&#x2F;a&gt;.
This is a personal blog, so I want to include information about me as a person.&lt;&#x2F;p&gt;
&lt;p&gt;This blog is built with the static site generator &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gohugo.io&#x2F;&quot;&gt;Hugo&lt;&#x2F;a&gt;, &lt;em&gt;the world&#x27;s fastest framework for building websites&lt;&#x2F;em&gt; - according to them.
I did not find an existing Hugo theme I liked, so I created one myself (drop me a note if you are interested).
My theme now needs to have a partial: it&#x27;s Hugo&#x27;s name for a reusable fragment with optional logic that can be embedded in a web page.
This partial should include my personal data in the correct format.&lt;&#x2F;p&gt;
&lt;p&gt;There is a specific format for personal data. It&#x27;s described in the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;schema.org&#x2F;Person&quot;&gt;person schema&lt;&#x2F;a&gt;.
Note that this schema includes references to other schemas.
If you work for a company, you can use the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;schema.org&#x2F;Organization&quot;&gt;organization schema&lt;&#x2F;a&gt; to provide more information with a &lt;code&gt;worksFor&lt;&#x2F;code&gt; entry.
I&#x27;ve selected the fields that I found most relevant and ended up with the following JSON structure:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  @context:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;              &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;https:&#x2F;&#x2F;schema.org&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  @type:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                 &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Person&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  name:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                  &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;John Doe&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  familyName:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;            &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Doe&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  givenName:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;             &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;John&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  image:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                 &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;https:&#x2F;&#x2F;example.org&#x2F;john_doe.webp&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  telephone:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;             &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;+491231234567&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  email:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                 &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;john.doe@example.org&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  url:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                   &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;https:&#x2F;&#x2F;john_doe.example.org&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  vatID:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                 &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;DE123456789&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  knowsLanguage:&lt;&#x2F;span&gt;&lt;span&gt;         [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;de-DE&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;en-US&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  address:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    @type:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;               &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;PostalAddress&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    streetAddress:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;       &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Am Hauptbahnhof&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    postalCode:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;          &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;60329&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    addressLocality:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Frankfurt am Main&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    addressRegion:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;       &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Hesse&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    addressCountry:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;      @type:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;             &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Country&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;      name:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;              &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;DE&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Since a theme should be like a blueprint that displays not only my personal data but the data of every person who might use it,
I separated the actual data from the presentation.
The &lt;code&gt;config.toml&lt;&#x2F;code&gt; is an ideal place to store some configuration parameters.
I created a new section with the name &lt;code&gt;params.person_ld&lt;&#x2F;code&gt; - &lt;code&gt;ld&lt;&#x2F;code&gt; stands for linked data - that contains all the personal data and that can be changed easily.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;params&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;person_ld&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;  person_name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;            =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;John Doe&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;  person_family_name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;     =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Doe&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;  person_given_name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;      =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;John&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;  person_image&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;           =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;https:&#x2F;&#x2F;example.org&#x2F;john_doe.webp&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;  person_telephone&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;       =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;+491231234567&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;  person_email&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;           =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;john.doe@example.org&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;  person_url&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;             =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;https:&#x2F;&#x2F;john_doe.example.org&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;  person_vatid&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;           =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;DE123456789&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;  person_knows_language&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;de-DE&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;en-US&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;  address_street&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;         =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Am Hauptbahnhof&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;  address_postal_code&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;    =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;60329&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;  address_locality&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;       =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Frankfurt am Main&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;  address_region&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;         =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Hesse&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;  address_country&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;        =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;DE&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On to the partial.
The structured data is embedded in a &lt;code&gt;&amp;lt;script&amp;gt;&lt;&#x2F;code&gt; tag in the web page in JSON format and has a special MIME type: &lt;code&gt;application&#x2F;ld+json&lt;&#x2F;code&gt;.
Since some configuration values can contain characters that need escaping in HTML,
I had to convince Hugo&#x2F;Go that the values can be safely rendered as-is with &lt;code&gt;safeHTML&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;script&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt; type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;application&#x2F;ld+json&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-embedded&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-embedded&quot;&gt;  &amp;quot;@context&amp;quot;:          &amp;quot;https:&#x2F;&#x2F;schema.org&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-embedded&quot;&gt;  &amp;quot;@type&amp;quot;:             &amp;quot;Person&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-embedded&quot;&gt;  &amp;quot;url&amp;quot;:               &amp;quot;{{ safeHTML .Site.Params.Person_ld.Person_url }}&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-embedded&quot;&gt;  &amp;lt;!-- More linked data in JSON format goes here --&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-embedded&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;script&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;the-problem&quot;&gt;The problem&lt;&#x2F;h2&gt;
&lt;p&gt;Contrary to what I had expected, this didn&#x27;t work at all.
Even though I had used &lt;code&gt;safeHTML&lt;&#x2F;code&gt;, some portions of the generated output still contained escaped characters.
That was not what I wanted.
I wanted the strings from the configuration to be shown as they were.
Instead, I ended up with this (examples, expected output in parentheses):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;https:\&#x2F;\&#x2F;example.org\&#x2F;john_doe.webp   (https:&#x2F;&#x2F;example.org&#x2F;john_doe.webp)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;\u002b49123123456                      (+491231234567)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;the-solution&quot;&gt;The solution&lt;&#x2F;h2&gt;
&lt;p&gt;After intensive Internet research and some testing of my own,
it turned out that the &lt;code&gt;&amp;lt;script&amp;gt;&lt;&#x2F;code&gt; tag was preventing the Hugo&#x2F;Go rendering engine from allowing unescaping certain parts,
leading to the escaped characters, no matter what I tried.&lt;&#x2F;p&gt;
&lt;p&gt;I know that it&#x27;s unsafe to allow this in the context of rendering arbitrary input, potentially from unsafe sources - like user input.
But that&#x27;s not the case here: all content comes from the &lt;code&gt;config.toml&lt;&#x2F;code&gt; file.
Normally, there is no chance of web user input reaching this place.&lt;&#x2F;p&gt;
&lt;p&gt;So I tried a solution for the partial &lt;code&gt;person-linked-data.html&lt;&#x2F;code&gt; that has no explicit &lt;code&gt;&amp;lt;script&amp;gt;&lt;&#x2F;code&gt; element anymore.
Instead, the element is printed as plain text, so that the Hugo&#x2F;Go parser doesn&#x27;t know for sure that it is inside a &lt;code&gt;&amp;lt;script&amp;gt;&lt;&#x2F;code&gt; block:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;{ safeHTML &amp;quot;&amp;lt;script type=\&amp;quot;application&#x2F;ld+json\&amp;quot;&amp;gt;&amp;quot; }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;@context&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-support z-function&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;          &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;https:&#x2F;&#x2F;schema.org&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;@type&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-support z-function&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;             &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Person&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;url&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-support z-function&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;               &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{{ safeHTML .Site.Params.Person_ld.Person_url }}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;--&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; More&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; linked&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; data&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; JSON&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; format&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; goes&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; here&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;{ safeHTML &amp;quot;&amp;lt;&#x2F;script&amp;gt;&amp;quot; }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While this works, it doesn&#x27;t feel right.
I really do want a valid &lt;code&gt;&amp;lt;script&amp;gt;&lt;&#x2F;code&gt; element in my partial.
So the only other working solution I found was in this &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;discourse.gohugo.io&#x2F;t&#x2F;hugos-behavior-in-script-tag&#x2F;20780&#x2F;4&#x2F;#post_5&quot;&gt;post by Sanmay Joshi&lt;&#x2F;a&gt;.
His solution uses the &lt;code&gt;printf&lt;&#x2F;code&gt; function.
You have to be aware that the surrounding double quotes are added automatically, so you have to omit them in the partial:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;script&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt; type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;application&#x2F;ld+json&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-embedded&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-embedded&quot;&gt;  &amp;quot;@context&amp;quot;:          &amp;quot;https:&#x2F;&#x2F;schema.org&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-embedded&quot;&gt;  &amp;quot;@type&amp;quot;:             &amp;quot;Person&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-embedded&quot;&gt;  &amp;quot;url&amp;quot;:               {{ printf &amp;quot;%s&amp;quot; .Site.Params.Person_ld.Person_url }},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-embedded&quot;&gt;  &amp;lt;!-- More linked data in JSON format goes here --&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-embedded&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;script&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I made sure the partial is only used if the configuration section &lt;code&gt;params.person_ld&lt;&#x2F;code&gt; exists.
For my theme, the following lines are included at the end of the &lt;code&gt;footer.html&lt;&#x2F;code&gt; partial:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{{ if .Site.Params.Person_ld }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;  &amp;lt;!--&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Display linked structured data &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;--&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {{ partial &amp;quot;person-linked-data.html&amp;quot; . }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{{ end }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;This solved the problem for me.
I hoped for a more elegant solution, maybe that &lt;code&gt;safeHTML&lt;&#x2F;code&gt; would work even under these circumstances.
But well, that wasn&#x27;t the case ...&lt;&#x2F;p&gt;
&lt;p&gt;For a blog, there is another schema that is also very useful and should be used to provide information about the articles.
Have a look at the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;schema.org&#x2F;BlogPosting&quot;&gt;blog posting schema&lt;&#x2F;a&gt; for more information.&lt;&#x2F;p&gt;
&lt;p&gt;If you know a better or more elegant solution to the problem, I would love to hear from you!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Entering the Battlesnake arena</title>
        <published>2021-08-22T00:00:00+00:00</published>
        <updated>2021-08-22T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/battlesnake-intro/"/>
        <id>https://weitzel.dev/blog/battlesnake-intro/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/battlesnake-intro/">&lt;p&gt;A short time ago I started learning to program in Rust.
Therefore, I&#x27;m looking for new toy projects to train my Rust programming skills.
I first heard about &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;play.battlesnake.com&#x2F;&quot;&gt;Battlesnake&lt;&#x2F;a&gt; in the podcast &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;DXqOXJvepgA&quot;&gt;Go Time&lt;&#x2F;a&gt; with Jon Calhoun, Brad van Vugt, and Mat Ryer.
This blog post uses Rust as a programming language, but only as an example to explain the implementation of strategies.
The information can be useful if you use other programming languages, too.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-the-aim-of-this-post&quot;&gt;What is the aim of this post?&lt;&#x2F;h2&gt;
&lt;p&gt;I started programming my first snake &lt;em&gt;Fairy Rust&lt;&#x2F;em&gt; a couple of weeks ago.
Up to now, I&#x27;ve spent about one working day of my spare time on this project.
During that time, I learned some lessons to make my snake better.
I want to share them with you.
If you start programming your own snake, maybe they can make your snake better as well.&lt;&#x2F;p&gt;
&lt;p&gt;In the future, I plan to write more articles about how I got my snake to improve - if I&#x27;m able to make it better.
I have some ideas that I will mention at the end of this article, so stay tuned.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-does-the-game-look-like&quot;&gt;What does the game look like?&lt;&#x2F;h2&gt;
&lt;p&gt;Battlesnake can be thought of as the evolution of the classic game &lt;em&gt;Snake&lt;&#x2F;em&gt; from Nokia, that appeared for the first time in 1998 on the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Nokia_6110&quot;&gt;Nokia 6110&lt;&#x2F;a&gt;.
The game idea is even older, but Nokia made it known to a broad audience.
The following game features four snakes fighting against each other.
The animation stops after 3 repetitions to minimize distraction.&lt;&#x2F;p&gt;
&lt;!-- Leave as HTML link so scaling [from 224px to 448px] works --&gt;
&lt;img src=&quot;resources&#x2F;media&#x2F;battlesnake-example-game.webp&quot; alt=&quot;Example game in Global Arena&quot; width=&quot;448&quot; height=&quot;448&quot;&gt;
&lt;h2 id=&quot;what-is-it&quot;&gt;What is it?&lt;&#x2F;h2&gt;
&lt;p&gt;Battlesnake is an online game where programs - and thus their programmers - play against each other.
You only need a running web server that implements four endpoints, a.k.a. the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.battlesnake.com&#x2F;api&quot;&gt;Battlesnake API&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The most important one is the &lt;code&gt;move&lt;&#x2F;code&gt; endpoint that handles the requests for your next move.
A request contains the description of the entire board prior to your move, for example:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the height and width of the board, e.g. 11 by 11 squares; each square is an address in a Cartesian coordinate system (X- and Y-axis)&lt;&#x2F;li&gt;
&lt;li&gt;the positions of all snakes on the board, where their heads and the rest of their body parts are&lt;&#x2F;li&gt;
&lt;li&gt;the current positions of food; eating food restores your health to 100 health points&lt;&#x2F;li&gt;
&lt;li&gt;where dangerous zones are (named &lt;em&gt;hazard sauce&lt;&#x2F;em&gt;); moving your head in it costs you not 1 health point but 15 per move&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Your &lt;code&gt;move&lt;&#x2F;code&gt; endpoint responds with a direction for moving the head of your snake. It&#x27;s either &lt;code&gt;Right&lt;&#x2F;code&gt;, &lt;code&gt;Up&lt;&#x2F;code&gt;, &lt;code&gt;Left&lt;&#x2F;code&gt;, or &lt;code&gt;Down&lt;&#x2F;code&gt;.
If your snake&#x27;s head is on point (2, 3), then &lt;code&gt;Right&lt;&#x2F;code&gt; will move it to (3, 3) and the rest of its body will follow.
Responding with &lt;code&gt;Down&lt;&#x2F;code&gt; would move it from (2, 3) to (2, 2).&lt;&#x2F;p&gt;
&lt;p&gt;The lower left square of the board is point (0, 0), the upper right square is (width-1, height-1).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;developing-your-own-snake&quot;&gt;Developing your own snake&lt;&#x2F;h2&gt;
&lt;p&gt;As a starting point, you can find starter snakes that implement a basic framework for handling requests for many programming languages on the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;BattlesnakeOfficial&quot;&gt;GitHub BattlesnakeOfficial account&lt;&#x2F;a&gt;.
They do not include any useful logic for letting your snake survive, but enable you to start with your own logic without spending too much time setting up your own framework for handling requests:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;BattlesnakeOfficial&#x2F;starter-snake-rust&quot;&gt;Rust&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;BattlesnakeOfficial&#x2F;starter-snake-python&quot;&gt;Python&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;BattlesnakeOfficial&#x2F;starter-snake-typescript&quot;&gt;Typescript&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;BattlesnakeOfficial&#x2F;starter-snake-javascript&quot;&gt;JavaScript&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;BattlesnakeOfficial&#x2F;starter-snake-go&quot;&gt;Go&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;BattlesnakeOfficial&#x2F;starter-snake-java&quot;&gt;Java&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;BattlesnakeOfficial&#x2F;starter-snake-ruby&quot;&gt;Ruby&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Your snake has only one primary goal: to survive (not die) by moving correctly. What can kill your snake:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;leaving the board (running into the wall)&lt;&#x2F;li&gt;
&lt;li&gt;running into another snake, head-on collisions are a special case&lt;&#x2F;li&gt;
&lt;li&gt;head-on collision with a snake at least as long as your snake&lt;&#x2F;li&gt;
&lt;li&gt;starving (running out of health; one move normally costs you 1 health point, but 15 with your head in the hazard sauce)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;When your snake is asked to make a move, it has to pick one of the four directions.
So an initial strategy should check all points that can be reached by following the respective direction, if they result in death.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;strategies-and-how-to-implement-them&quot;&gt;Strategies and how to implement them&lt;&#x2F;h2&gt;
&lt;p&gt;If a new game starts, you only see the head of your snake, but it already has a length of 3.
That&#x27;s because all other body parts are stacked beneath your head - all are at the same point.
Thus, you can freely move in any of the four directions, because there is nothing that would kill you.
But what is the best direction?&lt;&#x2F;p&gt;
&lt;p&gt;Whenever you have to choose from more than one possibility, not all of them might be equally good.
So I&#x27;ve chosen to create a set of &lt;code&gt;WeightedMovement&lt;&#x2F;code&gt; with all four possible movements and a &lt;code&gt;probability&lt;&#x2F;code&gt; of success attached to each movement.
How to calculate the probability is where we later spend most of the time.
But what&#x27;s already clear: we should pick the movement with the highest probability of success:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt; enum&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Movement&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    Right&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    Left&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    Up&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    Down&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; WeightedMovement&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; movement&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Movement&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; the movement&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; probability&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; f32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;   &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; probability of success&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; WeightedMovementSet&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; will be initialized with all four movements,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; all having a default&#x2F;starting probability&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; moves&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; HashSet&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;WeightedMovement&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As a consequence, these are the functions I&#x27;ve implemented for the &lt;code&gt;WeightedMovementSet&lt;&#x2F;code&gt;.
Alternatively, I could have chosen to not implement the &lt;code&gt;remove&lt;&#x2F;code&gt; function,
but set the &lt;code&gt;probability&lt;&#x2F;code&gt; of a move to a small value if it leads to immediate death.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; WeightedMovementSet&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; initializes the set with the four movements, each having a default probability&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; WeightedMovementSet&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; … &lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; removes a movement from the set, because it&amp;#39;s not a viable option&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; remove&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; movement&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Movement&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; … &lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; changes the probability of a movement, because we gained some insight&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; change_probability&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; movement&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Movement&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; new_probability&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; … &lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;   &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; picks the best movement - if there is one&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; pick_movement&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Movement&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; … &lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;start-with-the-four-movements&quot;&gt;Start with the four movements&lt;&#x2F;h3&gt;
&lt;p&gt;You should remove all movements that would immediately kill your snake from the set of possible movements and only look at the remaining ones.
There might be scenarios where you only can make a move that results in the death of your snake (leaving your set of possible movements empty),
so you should always have a default move that you make (like &lt;code&gt;Up&lt;&#x2F;code&gt;) if you have no viable option left.
Your snake will die anyway - sorry!&lt;&#x2F;p&gt;
&lt;p&gt;Starting from the point where your snake&#x27;s head is, you should identify and then check the points on the game board that you can reach with your next move.
These points should not be points where some sort of problem occurs - I will explain shortly.
To make life easier for me, I have attached the corresponding movement information to these checkpoints,
i.e. in which direction the head of my snake has to move to reach this point:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; CheckPoint&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;    point&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Point&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;    movement&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Movement&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The following function will return a collection of points that my snake&#x27;s head can reach in the next move.
I have to pass the position of my snake&#x27;s head (reference point) as an argument.
These checkpoints are the basis for further investigation:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; make_check_points&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;ref_point&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Point&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;CheckPoint&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        CheckPoint&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; point&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Point&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; ref_point&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; y&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; ref_point&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;y     &lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; movement&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Movement&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Right&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        CheckPoint&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; point&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Point&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; ref_point&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;     y&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; ref_point&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;y &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; movement&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Movement&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Up&lt;&#x2F;span&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        CheckPoint&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; point&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Point&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; ref_point&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; y&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; ref_point&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;y     &lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; movement&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Movement&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Left&lt;&#x2F;span&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        CheckPoint&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; point&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Point&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; ref_point&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;     y&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; ref_point&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;y &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; movement&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Movement&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Down&lt;&#x2F;span&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;eliminate-movements-leading-to-immediate-death&quot;&gt;Eliminate movements leading to immediate death&lt;&#x2F;h3&gt;
&lt;p&gt;The first obvious reasons for the immediate death of your snake are, if it moves its head to a point that ...&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;is outside the board&lt;&#x2F;li&gt;
&lt;li&gt;belongs to the body of a snake, either another one or your own snake&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;As an example, I&#x27;ll show you how to eliminate all movements that will make your snake run off the board.
A &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.battlesnake.com&#x2F;api&#x2F;objects&#x2F;battlesnake&quot;&gt;battlesnake&lt;&#x2F;a&gt; in JSON format looks like this,
so you can retrieve the point where the head is directly from this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;id&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;totally-unique-snake-id&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Sneky McSnek Face&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;health&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 54&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;body&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;x&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;y&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;x&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;y&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;x&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;y&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;latency&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;123&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l z-hl&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;head&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;x&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;y&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;length&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;shout&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;why are we shouting??&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;squad&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name z-json z-support z-type z-property-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The function needs the size (width and height) of the board, as well as the head position of your snake.
I have decided to let it directly remove all deadly movements from the set of possible movements,
as it doesn&#x27;t make sense to look at them from this point on.
We already know that our snake has no future with any of these movements.&lt;&#x2F;p&gt;
&lt;p&gt;It first calculates all the points (checkpoints) that can be reached by our snake&#x27;s head with its next move,
and then looks if a checkpoint is outside the board.
These points are not considered any further:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; avoid_wall&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;width&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; height&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; you&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Battlesnake&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; set&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; WeightedMovementSet&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; head&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;you&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;head&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; check_points&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; make_check_points&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;head&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; check_point&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;check_points&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; check_point&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;point&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; check_point&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;point&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; width&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; check_point&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;point&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;y&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; check_point&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;point&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;y &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; height&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;            &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; remove this movement from the set of possible movements&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;            set&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;remove&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;check_point&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;movement&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can now go ahead and implement a function that avoids movement into the body parts of your and all other snakes (exercise left to the reader).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;stacked-snakes&quot;&gt;Stacked snakes&lt;&#x2F;h2&gt;
&lt;p&gt;As soon as I implemented the function that avoids moving into a snake&#x27;s body,
I realized that it&#x27;s normally safe to move into the position of a snakes tail,
because it will have moved on by the time my snake makes that move.
But there is an exception to that rule: if a snake has eaten food during the prior move,
its tail will stay in the same position for another move.&lt;&#x2F;p&gt;
&lt;p&gt;Hm, do I then have to remember if there was food in the position where a snake&#x27;s head has moved?
I would have to store the information from the previous request, thereby creating global state.
Thankfully no! Whenever a snake eats food, it will grow and get another body part in a position where it has one already.
This part of its body becomes stacked.
And a stacked snake&#x27;s tail does not move.
A naive implementation to find out can look like this - checking if there&#x27;s more than one body part in a position:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; is_stacked&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;snake&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Battlesnake&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; bool&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;..&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;snake&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;body&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; j&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;..&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;snake&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;body&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;            &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; snake.body[n] is a point with X- and Y-coordinate &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; snake&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;body&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; snake&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;body&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;j&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;                return&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-language&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-constant z-language&quot;&gt;    false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So whenever a snake is stacked - either your own snake or another one - it&#x27;s not wise to move into the position of its tail.
If it&#x27;s not stacked, you can consider moving there.
You should still evaluate if another nearby snake can move into that spot, too.
If it&#x27;s at least as long as your snake, you might die in a head-on collision.
I&#x27;m therefore recommending downgrading the probability of success for such a move.&lt;&#x2F;p&gt;
&lt;p&gt;The tail of a snake is the last element of its body:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; get_tail&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;snake&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Battlesnake&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Point&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; there cannot be an empty snake body&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;    snake&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;body&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;last&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;dead-ends&quot;&gt;Dead ends&lt;&#x2F;h2&gt;
&lt;p&gt;As soon as your snake survives for more than just a couple of moves you start realizing that it does lots of stupid things.
It makes bad decisions, like moving into an area where there is not much room and no way out.
Sometimes it curls up, eventually running into itself.&lt;&#x2F;p&gt;
&lt;p&gt;How to solve these kinds of problems?
You need a strategy for looking ahead for more than just what does not immediately kill you in your next move.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Flood_fill&quot;&gt;flood-fill algorithm&lt;&#x2F;a&gt; comes to the rescue.
I will not explain it here, but will mention that it can help you identify areas that are too small, where you shouldn&#x27;t go.&lt;&#x2F;p&gt;
&lt;p&gt;The implementation and use of the &lt;strong&gt;flood-fill&lt;&#x2F;strong&gt; algorithm is probably &lt;strong&gt;the single most important thing&lt;&#x2F;strong&gt; to do,
as it will improve your snake beyond the majority of all other snakes.
And it has the potential for even further improvement:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;helps in finding the shortest path to food&lt;&#x2F;li&gt;
&lt;li&gt;helps in finding the shortest path out of the hazard sauce&lt;&#x2F;li&gt;
&lt;li&gt;assists in decision-making (which area contains how many heads, tails, food, and how far are they away)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;sudden-death-by-latency&quot;&gt;Sudden death by latency&lt;&#x2F;h2&gt;
&lt;p&gt;To participate in battlesnake games, your battlesnake&#x27;s API must be reachable over the Internet.
Since I have my own server, I decided to deploy my first battlesnake to it and run it from there.
The server is located in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.google.com&#x2F;maps&#x2F;place&#x2F;48%C2%B034&amp;#x27;08.7%22N+7%C2%B046&amp;#x27;56.0%22E&#x2F;@48.5690752,7.7822256,17&quot;&gt;Strasbourg, France&lt;&#x2F;a&gt;.
Currently, the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.battlesnake.com&#x2F;faq#which-cloud-provider-should-i-use&quot;&gt;Battlesnake Game Engine&lt;&#x2F;a&gt; is hosted in AWS US-WEST-2.
That&#x27;s nearly 6,000 miles apart.&lt;&#x2F;p&gt;
&lt;p&gt;Latency was below 200 ms for most parts of the games, but with sudden and unpredictable spikes.
Most spikes where above 500 ms, outside the time cap for the request.
Whenever this happens, the game engine repeats the last move for your battlesnake.
If your snake is head against the wall, it will be dead afterward.
It was especially bad in the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.battlesnake.com&#x2F;maps&#x2F;royale&quot;&gt;Royale&lt;&#x2F;a&gt; game mode,
where my snake was running into the wall after only a couple of moves every time.&lt;&#x2F;p&gt;
&lt;p&gt;To reduce latency, I looked for a cloud provider who had servers nearby the Battlesnake Game Engine.
Other requirements were that it was easy to use and affordable.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.linode.com&#x2F;&quot;&gt;Linode&lt;&#x2F;a&gt; offered:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;a region nearby: Fremont, CA&lt;&#x2F;li&gt;
&lt;li&gt;a promotion: $100 free for 60 days&lt;&#x2F;li&gt;
&lt;li&gt;low cost small instance: Nanode, 1 GB RAM, 25 GB storage, approx. $5&#x2F;month&lt;&#x2F;li&gt;
&lt;li&gt;1 TB of un-throttled network traffic&lt;&#x2F;li&gt;
&lt;li&gt;Ubuntu 20.04 LTS image, my preferred distro right now&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The Nanode instance is more than enough for my Rust implementation (stand-alone executable), that runs as a Linux service.
The entire system uses approx. 15 % of the available RAM, and CPU usage never goes above 10 %, below 1 % on average.
Estimated network traffic is less than 2 GB per month, well below the 1 TB high-speed limit.
Running my battlesnake on Linode gives me less than 50 ms latency consistently.
I&#x27;ve run into some timeouts as well, so they are not gone completely.
But the number of timeouts is so low, I barely recognize them anymore.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;deployment-to-linode&quot;&gt;Deployment to Linode&lt;&#x2F;h2&gt;
&lt;p&gt;In this section I will explain how to set up a Linux service for your battlesnake on a Linode instance,
how to start and stop it (even remotely), and how to deploy new versions of your snake with the push a button - sort of.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ssh-key-and-easy-access&quot;&gt;SSH key and easy access&lt;&#x2F;h3&gt;
&lt;p&gt;I assume you have created a Linode instance and it&#x27;s ready for use.
In order to work with your remote Linode server, you should create a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.linode.com&#x2F;docs&#x2F;guides&#x2F;use-public-key-authentication-with-ssh&#x2F;&quot;&gt;private&#x2F;public key pair&lt;&#x2F;a&gt; locally and store the public key under &lt;code&gt;SSH keys&lt;&#x2F;code&gt; in your Linode account.
Suppose you have created a key pair in your &lt;code&gt;~&#x2F;.ssh&lt;&#x2F;code&gt; directory with the name &lt;code&gt;id_linode&lt;&#x2F;code&gt;.
You then upload the contents of the file &lt;code&gt;id_linode.pub&lt;&#x2F;code&gt; to Linode as your public SSH key.
The other file &lt;code&gt;id_linode&lt;&#x2F;code&gt; contains your private key and should never be shared.&lt;&#x2F;p&gt;
&lt;p&gt;To easily connect to your Linode instance with &lt;code&gt;ssh linode&lt;&#x2F;code&gt;, add the following lines to your local &lt;code&gt;~&#x2F;.ssh&#x2F;config&lt;&#x2F;code&gt; file:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Host&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; linode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; use IPv4 address from your Linode instance&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  HostName&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 123.45.67.89&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  Port&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 22&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  User&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; root&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  IdentitiesOnly&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-language&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  IdentityFile&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ~&#x2F;.ssh&#x2F;id_linode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  ServerAliveInterval&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 15&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  StrictHostKeyChecking&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; no&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;setup-linux-service&quot;&gt;Setup Linux service&lt;&#x2F;h3&gt;
&lt;p&gt;Now it&#x27;s time to set up your service on your Linode instance.
In this example, I will name the service &lt;code&gt;battlesnake&lt;&#x2F;code&gt;, but you can name it however you like.
Your executable file (built with &lt;code&gt;cargo build --release&lt;&#x2F;code&gt;, or whatever language&#x2F;tool you are using) is stored in the directory &lt;code&gt;&#x2F;opt&#x2F;battlesnake&lt;&#x2F;code&gt; on the server with the name &lt;code&gt;battlesnake&lt;&#x2F;code&gt;.
If it&#x27;s not there yet, copy it to this location first.
Make sure it&#x27;s executable, e.g. with &lt;code&gt;sudo chmod +x &#x2F;opt&#x2F;battlesnake&#x2F;battlesnake&lt;&#x2F;code&gt;.
Create the file &lt;code&gt;&#x2F;lib&#x2F;systemd&#x2F;system&#x2F;battlesnake.service&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Unit&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Description&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;battlesnake service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ConditionPathExists&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;opt&#x2F;battlesnake&#x2F;battlesnake&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;After&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;network.target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Service&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;simple&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;User&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;www-data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Group&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;www-data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;LimitNOFILE&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;1024&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Restart&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;on-failure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;RestartSec&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;StartLimitInterval&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;60&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;WorkingDirectory&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;opt&#x2F;battlesnake&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ExecStart&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;opt&#x2F;battlesnake&#x2F;battlesnake&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;PermissionsStartOnly&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;StandardOutput&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;syslog&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;StandardError&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;syslog&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SyslogIdentifier&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;battlesnake&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Set environment variables (optional)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Environment&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;LOG_LEVEL&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;WARN&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Install&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;WantedBy&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;multi-user.target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You are now ready to work with your service:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;enable the service with &lt;code&gt;sudo systemctl enable battlesnake.service&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;start the service with &lt;code&gt;sudo systemctl start battlesnake.service&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;check status with &lt;code&gt;sudo systemctl status battlesnake.service&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Checking the status of your service should give you something like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; sudo systemctl status battlesnake.service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;●&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; battlesnake.service&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; battlesnake&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;     Loaded:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; loaded&lt;&#x2F;span&gt;&lt;span&gt; (&#x2F;lib&#x2F;systemd&#x2F;system&#x2F;battlesnake.service&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; enabled&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; vendor&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; preset:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; enabled&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;     Active:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; active&lt;&#x2F;span&gt;&lt;span&gt; (running&lt;&#x2F;span&gt;&lt;span&gt;) since Mon 2021-08-16 13:12:24 UTC&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; day&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 22h&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;   Main&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; PID:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 571&lt;&#x2F;span&gt;&lt;span&gt; (battlesnake&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;      Tasks:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 19&lt;&#x2F;span&gt;&lt;span&gt; (limit:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1071&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;     Memory:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 4.0M&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;     CGroup:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;system.slice&#x2F;battlesnake.service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;             └─571&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;opt&#x2F;battlesnake&#x2F;battlesnake&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;automatic-deployment&quot;&gt;Automatic deployment&lt;&#x2F;h3&gt;
&lt;p&gt;If you use a SSH key as described above and have a SSH configuration for &lt;code&gt;linode&lt;&#x2F;code&gt;,
then it&#x27;s easy to write a shell script - run on your development machine - that automates the deployment.
Here I&#x27;m deploying the executable &lt;code&gt;target&#x2F;release&#x2F;battlesnake&lt;&#x2F;code&gt; to the server.
You can even stop and start the service remotely:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;#!&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;bin&#x2F;bash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; uses SSH key from ~&#x2F;.ssh directory and configuration from ~&#x2F;.ssh&#x2F;config&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-support z-function&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;stop service&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ssh&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; root@linode&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;systemctl stop battlesnake&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-support z-function&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;copy executable file&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;scp&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; target&#x2F;release&#x2F;battlesnake&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; root@linode:&#x2F;opt&#x2F;battlesnake&#x2F;battlesnake&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-support z-function&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;start service&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ssh&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; root@linode&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;systemctl start battlesnake&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;what-s-coming-next&quot;&gt;What&#x27;s coming next?&lt;&#x2F;h2&gt;
&lt;p&gt;My snake is participating in all three global arenas, with mixed success.
It&#x27;s not completely bad, but there&#x27;s definitely room for improvement.
For example, it struggles to stay in the Platinum Level in the arenas &lt;em&gt;Global Arena&lt;&#x2F;em&gt; and &lt;em&gt;Global Royale&lt;&#x2F;em&gt;, oscillating between Gold Level and Platinum Level.
I still have a lot to do to improve it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;weitzel.dev&#x2F;blog&#x2F;battlesnake-intro&#x2F;resources&#x2F;media&#x2F;battlesnake-standings.webp&quot; alt=&quot;Example game in Global Arena&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I plan to write one or more follow-up posts. Some things I plan to implement and then write about are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;aggressive mode: go for head kills (or: don&#x27;t miss a chance to do it)&lt;&#x2F;li&gt;
&lt;li&gt;flood-fill algorithm in detail and further improvements&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Do you have some other suggestions for me? I would like to hear them.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;attributions&quot;&gt;Attributions&lt;&#x2F;h2&gt;
&lt;p&gt;The image used for this post&#x27;s card is taken from the Battlesnake&#x27;s Summer League 2021 banner.
I reached out to the Battlesnake team, and they kindly allowed me to use it.
Thank you!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Attributions</title>
        <published>2021-06-04T00:00:00+00:00</published>
        <updated>2021-06-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/pages/attributions/"/>
        <id>https://weitzel.dev/pages/attributions/</id>
        
        <content type="html" xml:base="https://weitzel.dev/pages/attributions/">&lt;h2 id=&quot;content-management-system&quot;&gt;Content management system&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;&quot;&gt;Zola&lt;&#x2F;a&gt; is my choice for managing content and creating a static website from it.
It is your one-stop static site engine.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cascading-style-sheets&quot;&gt;Cascading style sheets&lt;&#x2F;h2&gt;
&lt;p&gt;For styling, I use the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tailwindcss.com&quot;&gt;Tailwind CSS&lt;&#x2F;a&gt; framework by Adam Wathan.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;artwork&quot;&gt;Artwork&lt;&#x2F;h2&gt;
&lt;p&gt;I use free artwork on this site:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Free icons (MIT License) from
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;refactoringui&#x2F;heroicons&quot;&gt;Heroicons&lt;&#x2F;a&gt; by Refactoring UI Inc.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Free images under the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;license&quot;&gt;Unsplash License&lt;&#x2F;a&gt; from
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@zgc1993&quot;&gt;冬城&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@cuatrobel&quot;&gt;Abel Pérez&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@alexander_ant&quot;&gt;Alexander Ant&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@sharonmccutcheon&quot;&gt;Alexander Grey&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Andrew Buchanan&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@drwmrk&quot;&gt;Andrew Stutesman&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@brett_jordan&quot;&gt;Brett Jordan&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@woodpecker65&quot;&gt;Christian Stahl&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@clintadair&quot;&gt;Clint Adair&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@danielcgold&quot;&gt;Dan Gold&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@davelowephoto&quot;&gt;Dave Lowe&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@davidclode&quot;&gt;David Clode&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@hasanalmasi&quot;&gt;Hasan Almasi&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@jasonrosewell&quot;&gt;Jason Rosewell&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@jaysung&quot;&gt;Jehyun Sung&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@kathhh&quot;&gt;Katherine Fleitas&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@lionel28&quot;&gt;Lionel Hesry&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@mmmarq&quot;&gt;Marcelo Marques&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Marian Kroell&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@kerber&quot;&gt;Marko Blažević&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@markusspiske&quot;&gt;Markus Spiske&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@markuswinkler&quot;&gt;Markus Winkler&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@max_williams&quot;&gt;Max Williams&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Mohammad Ali Berenji&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@nhulz&quot;&gt;Nathan Hulsey&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@jannerboy62&quot;&gt;Nick Fewings&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@olav_tvedt&quot;&gt;Olav Tvedt&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Omar Flores&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@pawel_czerwinski&quot;&gt;Pawel Czerwinski&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@theshubhamdhage&quot;&gt;Shubham Dhage&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Sophie Vinetlouis&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@steve_j&quot;&gt;Steve Johnson&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@srz&quot;&gt;Sydney Rae&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@timmarshall&quot;&gt;Tim Marshall&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@timmossholder&quot;&gt;Tim Mossholder&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@karton55&quot;&gt;Vitalik Vynarchyk&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;@vivaantrivedii&quot;&gt;Vivaan Trivedii&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Some Unsplash profiles are no longer available.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;libraries-and-assets&quot;&gt;Libraries and assets&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;katex.org&#x2F;&quot;&gt;KaTeX&lt;&#x2F;a&gt; (MIT License) for math rendering.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mermaid.js.org&#x2F;&quot;&gt;Mermaid&lt;&#x2F;a&gt; (MIT License) for diagrams.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;howlerjs.com&#x2F;&quot;&gt;Howler.js&lt;&#x2F;a&gt; (MIT License) for the custom audio player.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lucaong.github.io&#x2F;minisearch&#x2F;&quot;&gt;MiniSearch&lt;&#x2F;a&gt; (MIT License) for client-side search.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;artalk.js.org&#x2F;&quot;&gt;Artalk&lt;&#x2F;a&gt; (MIT License) for optional comments.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;getzola&#x2F;giallo&quot;&gt;Giallo&lt;&#x2F;a&gt; (EUPL-1.2 License) for syntax highlighting.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Text scrambler</title>
        <published>2020-11-14T00:00:00+00:00</published>
        <updated>2020-11-14T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/text-scrambler/"/>
        <id>https://weitzel.dev/blog/text-scrambler/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/text-scrambler/">&lt;h2 id=&quot;what-it-does&quot;&gt;What it does&lt;&#x2F;h2&gt;
&lt;p&gt;If you rearrange the characters in a word, but leave the first and last character in place, your brain can still make sense of this nonsense most of the time.
Why?
Researchers aren&#x27;t entirely sure, but they have some suspicions.
They think part of the reason the result is still readable is because our brains are able to use context to make predictions about what&#x27;s to come.&lt;&#x2F;p&gt;
&lt;p&gt;This post lets you interactively examine if this works for you.
Try it out for yourself.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;test-it-online&quot;&gt;Test it online!&lt;&#x2F;h2&gt;
&lt;p&gt;Type a text into the text area or just copy and paste some text. Hit the &lt;code&gt;scramble&lt;&#x2F;code&gt; button and try to read the result.&lt;&#x2F;p&gt;
&lt;div id=&quot;text-scrambler&quot; class=&quot;mt-8 bg-primary-950 rounded-md&quot;&gt;
    &lt;div class=&quot;shadow overflow-hidden rounded-md&quot;&gt;
        &lt;div class=&quot;p-4 bg-neutral-900&quot;&gt;
            &lt;div class=&quot;grid grid-cols-6&quot;&gt;
                &lt;div class=&quot;col-span-6&quot;&gt;
                    &lt;label for=&quot;unscrambled-text&quot; class=&quot;block text-sm font-medium leading-5 text-neutral-200&quot;&gt;Your text&lt;&#x2F;label&gt;
                    &lt;textarea rows=&quot;5&quot; placeholder=&quot;Enter text here&quot; id=&quot;unscrambled-text&quot; class=&quot;mt-2 form-textarea block w-full p-2 border border-neutral-600 rounded-md shadow-sm focus:outline-none focus:shadow-outline focus:border-primary-300 transition duration-150 ease-in-out text-sm leading-5&quot;&gt;&lt;&#x2F;textarea&gt;
                &lt;&#x2F;div&gt;
                &lt;div class=&quot;col-span-6&quot;&gt;
                    &lt;p id=&quot;scrambled-text&quot; class=&quot;block text-sm font-medium leading-5 text-neutral-200&quot;&gt;Scrambled text will appear here.&lt;&#x2F;p&gt;
                &lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
        &lt;div class=&quot;p-4 bg-primary-800 text-right&quot;&gt;
            &lt;button id=&quot;calcButton&quot; class=&quot;py-2 px-4 border border-transparent text-sm leading-5 font-medium rounded-md text-neutral-950 bg-primary-300 shadow-sm hover:bg-primary-200 focus:outline-none focus:shadow-outline active:bg-primary-400 transition duration-150 ease-in-out&quot; &gt;
                scramble
            &lt;&#x2F;button&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;what-is-a-word&quot;&gt;What is a word?&lt;&#x2F;h2&gt;
&lt;p&gt;In order to scramble a word in the way mentioned above, we first have to agree on what a word is.
For the purpose of this post, I&#x27;ve decided to define a word as a series of characters from the German alphabet.
Lowercase and uppercase characters are allowed.
If you want to define your own alphabet, just change this variable.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; English and German only&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; alphabet&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;  &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;abcdefghijklmnopqrstuvwxyzäöüß&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;  &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜẞ&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;create-a-random-permutation-of-letters&quot;&gt;Create a random permutation of letters&lt;&#x2F;h2&gt;
&lt;p&gt;This function rearranges the elements of array &lt;code&gt;a&lt;&#x2F;code&gt; by constructing a new one.
It does this by picking a random element from the array and then deleting it, until there are no more elements left.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; getRandomPermutation&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; permutation&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  while&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable&quot;&gt;length&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; randomIndex&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;      Math&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;floor&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;Math&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;random&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; Math&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;floor&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable&quot;&gt;length&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; element&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;randomIndex&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;    permutation&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;push&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;element&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;    a&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;splice&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;randomIndex&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; permutation&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;scramble-an-entire-text&quot;&gt;Scramble an entire text&lt;&#x2F;h2&gt;
&lt;p&gt;This function scrambles a text by iterating over each character.
If the character is part of our alphabet, it&#x27;s collected in the &lt;code&gt;word&lt;&#x2F;code&gt; variable.
Otherwise, the character is put into the &lt;code&gt;result&lt;&#x2F;code&gt; array that will become our result.&lt;&#x2F;p&gt;
&lt;p&gt;Whenever we handle a character that is not part of our alphabet, we see if we have collected enough characters before that we can now rearrange.
If that&#x27;s not the case, we just put all characters from the &lt;code&gt;word&lt;&#x2F;code&gt; variable into &lt;code&gt;result&lt;&#x2F;code&gt;.
To make sure we do that at the end of our text, we simply append a non-alphabet character at the end of the text that is thrown away afterwards.
I&#x27;ve chosen the &lt;code&gt;$&lt;&#x2F;code&gt; characters for this.&lt;&#x2F;p&gt;
&lt;p&gt;If we have enough characters (we need more than 3), we leave the first character &lt;code&gt;word[0]&lt;&#x2F;code&gt; and the last character &lt;code&gt;word[word.length - 1]&lt;&#x2F;code&gt; in place and create a random permutation from the characters between them.
The result is transferred to the &lt;code&gt;result&lt;&#x2F;code&gt; variable.&lt;&#x2F;p&gt;
&lt;p&gt;We then have to empty the &lt;code&gt;word&lt;&#x2F;code&gt; variable to be ready for the next word.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; scrambleText&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;text&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; result&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; word&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;  &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; make sure that text ends with a non-alphabet ($) character,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;  &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; because this activates the else case and clears the word&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;  (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;text&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;split&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;forEach&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;alphabet&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;includes&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;      &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; store alphabet characters in word&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;      word&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;push&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;    }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; else&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;      &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; handle word first&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;      if&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;word&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable&quot;&gt;length&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; all word characters except first and last one&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;        const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; middle&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; word&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;slice&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; word&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable&quot;&gt;length&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;        result&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;push&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;word&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;        result&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;push&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;...&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;getRandomPermutation&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;middle&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;        result&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;push&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;word&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;word&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable&quot;&gt;length&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;      }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; else&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;        result&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;push&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;...&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;word&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;      &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; reset word&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;      word&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;      &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; push non-alphabet character to result&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;      result&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;push&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;  }&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;  &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; remove trailing $ character&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;  result&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;pop&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; result&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;join&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;put-it-together&quot;&gt;Put it together&lt;&#x2F;h2&gt;
&lt;p&gt;Put the program together and run it by passing a text to the &lt;code&gt;scrambleText&lt;&#x2F;code&gt; function.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; text&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;  &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;A text is still readable if you rearrange the letters of words, ...&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;console&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;scrambleText&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;text&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You might get an output similar to this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;A txet is siltl rbaladee if you re-ararnge the ltetres of wodrs, ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;alternative-rust-version&quot;&gt;Alternative Rust version&lt;&#x2F;h2&gt;
&lt;p&gt;The same code translated into Rust doesn&#x27;t look much different.
For the permutation of the middle of a word I used the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;rand&#x2F;&quot;&gt;rand&lt;&#x2F;a&gt; crate.
Note that I iterate over the characters of the text which will not work for all Unicode characters.
You can fix this by using the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;unicode-segmentation&#x2F;&quot;&gt;unicode-segmentation&lt;&#x2F;a&gt; crate.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; rand&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;seq&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;SliceRandom&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; rand&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;thread_rng&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Use type alias to make source code more readable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Text&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Scrambles a word (reference to vector of char) in place and returns it&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; scramble_word&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;word&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Text&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Text&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; len&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; word&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; len&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;        word&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;..&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;len&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;shuffle&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; thread_rng&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;    word&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Takes an alphabet and a string slice and scrambles it, returns a String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; scramble_text&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; alphabet&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;chars&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Text&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; text&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;chars&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Text&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Make sure that text ends with a non-alphabet ($) character,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; because this activates the else case and clears the word&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;    text&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Tuple of word (component 0) and result (component 1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; r&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; text&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;fold&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Text&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Text&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; acc&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; alphabet&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;contains&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;                acc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;                acc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;append&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;scramble_word&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; acc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;                &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Reset word&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;                acc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Text&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;                &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Push non-alphabet character to result&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;                acc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;            acc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Remove trailing terminal character&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;pop&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; alphabet&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;abcdefghijklmnopqrstuvwxyzäöüßABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜẞ&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; text&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;A text is still readable if you rearrange the letters of words, ...&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; scramble_text&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;alphabet&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; text&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While translating the source code from JavaScript to Rust,
I experimented with the &lt;code&gt;scan&lt;&#x2F;code&gt; function from the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;trait.Iterator.html#method.scan&quot;&gt;iterator trait&lt;&#x2F;a&gt;.
It promised more flexibility, but it&#x27;s likely &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;users.rust-lang.org&#x2F;t&#x2F;lifetime-problem-with-scan-from-iterator-trait&#x2F;54509&quot;&gt;not a suitable option&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;script src=&quot;resources&#x2F;js&#x2F;text-scrambler.js&quot; integrity=&quot;sha384-u3VKpOgc&#x2F;yOQOMnGLAQrE5gB3xu68lQI&#x2F;QUH0MfzsGMG7+72i1tmfRm4xwmsSlGq&quot;&gt;&lt;&#x2F;script&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The Game of Fifteen</title>
        <published>2020-06-11T00:00:00+00:00</published>
        <updated>2020-06-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/game-of-fifteen/"/>
        <id>https://weitzel.dev/blog/game-of-fifteen/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/game-of-fifteen/">&lt;p&gt;The Game of Fifteen is a sliding puzzle that consists of a square with tiles numbered from 1 to 15 in random order with one tile missing.
To solve the puzzle, you must place the tiles in order by moving tiles to the empty space.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-to-play&quot;&gt;How to play&lt;&#x2F;h2&gt;
&lt;p&gt;Play the game online by clicking&#x2F;tapping on the tile you want to move.
Only tiles neighboring the empty space can be moved.
Once you solve the puzzle, the tiles will not move anymore.
Just play a new game by clicking the button.
I can guarantee you that every game presented here is solvable.
Read below for an explanation.&lt;&#x2F;p&gt;
&lt;p&gt;Hint: if your browser doesn&#x27;t display the board correctly, try clearing your browser cache and try again.&lt;&#x2F;p&gt;
&lt;div id=&quot;board&quot;&gt;
    &lt;div class=&quot;m-4 grid grid-flow-row grid-cols-4 grid-rows-4 h-64 w-64 gap-1&quot;&gt;
        &lt;div id=&quot;f0&quot;  class=&quot;&quot;&gt;&lt;&#x2F;div&gt;
        &lt;div id=&quot;f1&quot;  class=&quot;&quot;&gt;&lt;&#x2F;div&gt;
        &lt;div id=&quot;f2&quot;  class=&quot;&quot;&gt;&lt;&#x2F;div&gt;
        &lt;div id=&quot;f3&quot;  class=&quot;&quot;&gt;&lt;&#x2F;div&gt;
        &lt;div id=&quot;f4&quot;  class=&quot;&quot;&gt;&lt;&#x2F;div&gt;
        &lt;div id=&quot;f5&quot;  class=&quot;&quot;&gt;&lt;&#x2F;div&gt;
        &lt;div id=&quot;f6&quot;  class=&quot;&quot;&gt;&lt;&#x2F;div&gt;
        &lt;div id=&quot;f7&quot;  class=&quot;&quot;&gt;&lt;&#x2F;div&gt;
        &lt;div id=&quot;f8&quot;  class=&quot;&quot;&gt;&lt;&#x2F;div&gt;
        &lt;div id=&quot;f9&quot;  class=&quot;&quot;&gt;&lt;&#x2F;div&gt;
        &lt;div id=&quot;f10&quot; class=&quot;&quot;&gt;&lt;&#x2F;div&gt;
        &lt;div id=&quot;f11&quot; class=&quot;&quot;&gt;&lt;&#x2F;div&gt;
        &lt;div id=&quot;f12&quot; class=&quot;&quot;&gt;&lt;&#x2F;div&gt;
        &lt;div id=&quot;f13&quot; class=&quot;&quot;&gt;&lt;&#x2F;div&gt;
        &lt;div id=&quot;f14&quot; class=&quot;&quot;&gt;&lt;&#x2F;div&gt;
        &lt;div id=&quot;f15&quot; class=&quot;&quot;&gt;&lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;mt-4&quot;&gt;
    &lt;button id=&quot;playButton&quot; class=&quot;py-2 px-4 border border-transparent text-sm leading-5 font-medium rounded-md text-neutral-950 bg-primary-300 shadow-sm hover:bg-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 focus:ring-offset-neutral-950 active:bg-primary-600 transition duration-150 ease-in-out&quot;&gt;
        new game
    &lt;&#x2F;button&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;parity-of-a-permutation&quot;&gt;Parity of a permutation&lt;&#x2F;h2&gt;
&lt;p&gt;For the Game of Fifteen, a permutation of the numbers 1 to 15 is a state of the game if read line by line - like a book.
Some smart people have figured out, that an even parity (is dividable by 2, like 42) is an invariant of a solvable permutation of the Game of Fifteen.
In computer science, an invariant is a condition that is always true, i.e. doesn&#x27;t change for a section of code.&lt;&#x2F;p&gt;
&lt;p&gt;The parity of a permutation is simply the number of inversions.
An inversion happens when an element with a lower index has a higher value than a value at a higher index.&lt;&#x2F;p&gt;
&lt;p&gt;Examples:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;1, 2, 3&lt;&#x2F;code&gt; has no inversions, all elements are in order&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;2, 3, 1&lt;&#x2F;code&gt; has two inversions, because &lt;code&gt;2&lt;&#x2F;code&gt; is greater than &lt;code&gt;1&lt;&#x2F;code&gt; and &lt;code&gt;3&lt;&#x2F;code&gt; is greater than &lt;code&gt;1&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;1, 3, 2&lt;&#x2F;code&gt; has only one inversion, &lt;code&gt;3&lt;&#x2F;code&gt; is greater than &lt;code&gt;2&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;There are about 1.3 Trillion (Billion for us people in Central Europe) possible permutations of the numbers 1 to 15.
Only half of them have an even parity.
When we calculate a random permutation for the start of a game, it then makes sense to filter out all the permutations with an odd parity.
Because we do not want to present an unsolvable game.&lt;&#x2F;p&gt;
&lt;p&gt;Here is a fragment of source code that calculates the parity and checks if it&#x27;s even for the examples from above.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; for (let i = 0; i &amp;lt; limit; i += 1) {...} vs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; range0(limit).forEach((i) =&amp;gt; {...})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; range0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;limit&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;...&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Array&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;limit&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;keys&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; isEvenPermutation&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; parity&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; %&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; ===&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; parity&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; range0&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor&quot;&gt;  .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; range0&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;j&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; j&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; p&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; p&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;j&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable&quot;&gt;length&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor&quot;&gt;  .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;reduce&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;agg&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt; v&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; agg&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; v&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; true, 0 inversions&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;console&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;isEvenPermutation&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; true, 2 inversions&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;console&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;isEvenPermutation&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; false, 1 inversion&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;console&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;isEvenPermutation&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;source-code&quot;&gt;Source code&lt;&#x2F;h2&gt;
&lt;p&gt;I have created this &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;thomasweitzel&#x2F;3fd3197616f0299a2935972edd68bd4a&quot;&gt;GitHub Gist&lt;&#x2F;a&gt; with the complete HTML page including the JavaScript source code.
It runs in the browser and uses just &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tailwindcss.com&quot;&gt;Tailwind CSS&lt;&#x2F;a&gt; for styling and plain ES6-style JavaScript.
The source code can be used for all square board sizes, not only 4 by 4.
You have to adjust the boards GUI or dynamically generate it - it&#x27;s easy.&lt;&#x2F;p&gt;
&lt;div class=&quot;hidden bg-primary-300 bg-primary-500 bg-primary-600 bg-primary-800 bg-primary-950 bg-warn-700 text-neutral-950 text-fail-200 border-primary-700 border-warn-600 border-transparent focus:ring-primary-500 focus:ring-offset-neutral-950&quot;&gt;&lt;&#x2F;div&gt;
&lt;script src=&quot;resources&#x2F;js&#x2F;game-of-fifteen.js&quot; integrity=&quot;sha384-JxrdBI5c+wPKQv&#x2F;3jeIZHhvFK5u658hFW&#x2F;SaEFvVQZkE3Obo6boo+t3mu8dXS&#x2F;ts&quot;&gt;&lt;&#x2F;script&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Working with Rust&#x27;s num-bigint</title>
        <published>2020-05-24T00:00:00+00:00</published>
        <updated>2020-05-24T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/rust-num-bigint/"/>
        <id>https://weitzel.dev/blog/rust-num-bigint/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/rust-num-bigint/">&lt;h2 id=&quot;why-rust&quot;&gt;Why Rust&lt;&#x2F;h2&gt;
&lt;p&gt;A couple of years ago, I started learning Go.
It&#x27;s a nice little language that I like very much, but some things still bother me.
Go has no generics, no adequate support for functional style, and no tail call optimization.
In my view, most other things the language got right.
I know that some of these topics are the subject of heated debates, but the views presented here are mine.
What I love most is that it&#x27;s a simple and mostly clean language, has a superb standard library,
excellent support for templating, and &quot;implicit&quot; interface implementation.&lt;&#x2F;p&gt;
&lt;p&gt;I stumbled across Rust at the same time, but from what I can remember,
people were having difficulties due to a steep learning curve, and a standard library that was missing a few bits and pieces.
So I went with Go.
Rust was still on my radar.
I found some time recently and started learning it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-problem-to-solve&quot;&gt;The problem to solve&lt;&#x2F;h2&gt;
&lt;p&gt;Whenever I learn a new language, I try to solve some problems with a limited scope.
Only after I have successfully solved some of them, I try to use my skills in a little project.
This time I went with HackerRank&#x27;s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.hackerrank.com&#x2F;challenges&#x2F;marcs-cakewalk&#x2F;problem&quot;&gt;Marc&#x27;s Cakewalk&lt;&#x2F;a&gt; problem.
Because it&#x27;s too simple, I added some extra difficulty.
The original problem is solvable by using the &lt;code&gt;u64&lt;&#x2F;code&gt; data type, because it restricts the size &lt;code&gt;n&lt;&#x2F;code&gt; of the input vector.
So I removed this restriction, which was 40 elements.
Now I needed an arbitrary-sized integer type.
Rust has no arbitrary-sized integer type, and there&#x27;s no ready-to-use solution in the standard library.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-crate-num-bigint&quot;&gt;The crate num-bigint&lt;&#x2F;h2&gt;
&lt;p&gt;For my additional difficulty to work,
I had to calculate e.g. &lt;code&gt;42 * 2^100000&lt;&#x2F;code&gt; as a term and add it together with other terms of the same structure.
I found out that the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;num-bigint&quot;&gt;crate &lt;code&gt;num-bigint&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; could solve my problem,
because it is able to handle arbitrary-sized integers.
I wasn&#x27;t able to find helpful examples on the Internet.
All I found was the source code and the documentation of the crate itself.
So I had to use this.
Remember, I&#x27;m still trying to learn Rust and I&#x27;m not familiar with all of its concepts and conventions,
let alone the standard library and the crate ecosystem.&lt;&#x2F;p&gt;
&lt;p&gt;I figured it out eventually.
Big-integer multiplication, addition, and the power function with a fixed-sized integer as exponent was all I needed.
Addition and multiplication are really easy, because it&#x27;s done by operator-overloading.
The power function was the most challenging, because I didn&#x27;t know how to properly read the crate&#x27;s documentation.
Once I learned that, it was easy, too - just use the pow trait.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;solution-with-rust&quot;&gt;Solution with Rust&lt;&#x2F;h2&gt;
&lt;p&gt;So here is the Rust source code for the problem.
You cannot use it as part of a HackerRank submission, because it uses an external crate, which HackerRank does not allow.
The solution partly has a functional style, except that &lt;code&gt;sort&lt;&#x2F;code&gt; and &lt;code&gt;reverse&lt;&#x2F;code&gt; have side effects.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;extern&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; crate&lt;&#x2F;span&gt;&lt;span&gt; num_bigint&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;extern&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; crate&lt;&#x2F;span&gt;&lt;span&gt; num_traits&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; num_bigint&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;BigInt&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; num_traits&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;pow&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; cs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;7&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 6&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; example&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; miles&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; marcs_cakewalk&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; cs&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; miles&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_str_radix&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; marcs_cakewalk&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;cs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; BigInt&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;    cs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;sort&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;    cs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;reverse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;    cs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;enumerate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; zip index and value into tuple&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;v&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; BigInt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;v&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; pow&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;BigInt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; i&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;fold&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;            BigInt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;            |&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;sum&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; value&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; sum&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; value&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;solution-with-go&quot;&gt;Solution with Go&lt;&#x2F;h2&gt;
&lt;p&gt;Go has an arbitrary-sized integer type in the standard library called &lt;code&gt;big.Int&lt;&#x2F;code&gt;.
A solution with this type, even though it is not written in a functional style, could use the following function.
HackerRank would even allow it as part of a solution, because it only uses the standard library.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; marcsCakewalk&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;cs&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;int64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;big&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Int&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;	sort&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;SliceStable&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;cs&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt; b&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; bool&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; cs&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; cs&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;	sum&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; big&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;NewInt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;	for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; range&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; cs&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;		b2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; big&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;NewInt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;		f1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; big&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;NewInt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;cs&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;		f2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; b2&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Exp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;b2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; big&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;NewInt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;int64&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-language&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 2 ** i&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;		sum&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; sum&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;sum&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; f1&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Mul&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;f1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; f2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;	return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; sum&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;If you are learning Rust and you need the crate &lt;code&gt;num-bigint&lt;&#x2F;code&gt;,
and you do not find information on how to use it in a limited scenario similar to the one mentioned above,
this article might help you.
At least it will help me sometime in the future when I need functionality from this crate again and have forgotten how to use it.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The Monty-Hall-Problem</title>
        <published>2020-04-26T00:00:00+00:00</published>
        <updated>2020-04-26T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/monty-hall-problem/"/>
        <id>https://weitzel.dev/blog/monty-hall-problem/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/monty-hall-problem/">&lt;h2 id=&quot;welcome-to-the-monty-hall-show&quot;&gt;Welcome to The Monty-Hall-Show&lt;&#x2F;h2&gt;
&lt;p&gt;The Monty-Hall-Show was a popular show back in the day when contestants could
go on this game show and might go home with the car of their dreams. The game show
host was a very famous guy named Monty Hall. In this problem, which never happened like this in reality,
Monty would come on to the show, and he would present three doors.
He would give a contestant the chance to pick one of the doors.
Behind only one of those doors was the dream car. Behind the other two doors were
goats or just something nobody really wants.&lt;&#x2F;p&gt;
&lt;p&gt;It looks like a 1&#x2F;3 chance of getting a dream car.
Suppose the contestant picks door number one and Monty goes over to the two doors she didn&#x27;t pick.
Since Monty knew exactly where the car was, he would open one of the doors that had a goat behind it.
Then Monty would look at the contestant and ask: &quot;Do you still like door number one or do you want to switch?&quot;&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s only one door left to switch to. Is the contestant going to stay with
her choice or is she going to make that leap to the other door?
Very often contestants would stand there agonized.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-s-the-best-strategy&quot;&gt;What&#x27;s the best strategy?&lt;&#x2F;h2&gt;
&lt;p&gt;A remarkable thing about this simple problem is that it has sparked just endless debate.
While the show was running, I don&#x27;t recall anybody ever proposing a dedicated strategy.
But there is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;cXqDIFUB7YU&quot;&gt;a dedicated strategy&lt;&#x2F;a&gt; one should follow: always switch doors, because it doubles the chances!&lt;&#x2F;p&gt;
&lt;p&gt;There is a 1&#x2F;3 chance the car is behind the initially picked door.
That means there must be a 2&#x2F;3 chance the car is somewhere else.
Since we know that somewhere else cannot be the door that was just opened by Monty,
it has to be the other unopened door.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;putting-it-to-the-extreme&quot;&gt;Putting it to the extreme&lt;&#x2F;h2&gt;
&lt;p&gt;Unconvinced? There is a way to understand this in a more extreme example.
Imagine not having three doors, but 100 doors. Let&#x27;s imagine that we&#x27;re
playing the same kind of game. Monty is going to give the contestant
an opportunity to pick a door. There&#x27;s only a 1&#x2F;100 chance the dream car
is behind the door that is picked. Compared to the original setting,
the chances are now very slim to get the car.&lt;&#x2F;p&gt;
&lt;p&gt;Monty now opens 98 of those other 99 doors.
Hint: Monty is not opening one door; he is always opening all remaining doors except one.
Behind every door is a goat.
He asks the contestant if she wants to switch to that other unopened door.
Just because of the sheer number of doors, maybe this is a little clearer.&lt;&#x2F;p&gt;
&lt;p&gt;There is a 99&#x2F;100 chance the car is behind one of the doors the contestant didn&#x27;t pick.
With the original setting, some people say that it&#x27;s a 50&#x2F;50 chance if there are only two unopened doors left,
so the contestant can either stay with her initial choice or switch, it doesn&#x27;t matter.
Would you say the same now with the 100 doors example? Because if you said so,
you&#x27;re effectively saying that if you pick one door out of 100 doors, in half of the cases you get a dream car.
Ha, you know that is wrong! Even your guts should tell you in the 100 doors example to switch doors.
Suddenly it seems like a no-brainer.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;simulation-time&quot;&gt;Simulation time&lt;&#x2F;h2&gt;
&lt;p&gt;Are you still unconvinced? I&#x27;ve written a little simulator that can help you with that.
Enter the number of doors, the number of tries, and it will make an experiment and count
the wins for both scenarios for you (keep&#x2F;switch).
See for yourself. &lt;code&gt;Doors&lt;&#x2F;code&gt; must be greater than 2 and &lt;code&gt;Tries&lt;&#x2F;code&gt; must be a positive number.&lt;&#x2F;p&gt;
&lt;div id=&quot;monty-hall-simulator&quot; class=&quot;mt-8 bg-primary-900 rounded-md&quot;&gt;
    &lt;div class=&quot;p-4 md:p-8 max-w-2xl&quot;&gt;
        &lt;div class=&quot;md:grid md:grid-cols-3 md:gap-6&quot;&gt;
            &lt;div class=&quot;md:col-span-1&quot;&gt;
                &lt;p class=&quot;text-lg font-bold leading-6 text-neutral-200&quot;&gt;Wins by strategy&lt;&#x2F;p&gt;
                &lt;p id=&quot;values&quot; class=&quot;mt-2 text-sm text-neutral-200 leading-5&quot;&gt;&lt;&#x2F;p&gt;
                &lt;p id=&quot;result&quot; class=&quot;mt-2 text font-bold leading-5 text-neutral-300&quot;&gt;
                    Press calculate ...
                &lt;&#x2F;p&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;mt-4 md:mt-0 md:col-span-2&quot;&gt;
                &lt;div class=&quot;shadow overflow-hidden sm:rounded-md&quot;&gt;
                    &lt;div class=&quot;px-4 py-5 bg-neutral-900 sm:p-6&quot;&gt;
                        &lt;div class=&quot;grid grid-cols-6 gap-6&quot;&gt;
                            &lt;div class=&quot;col-span-3&quot;&gt;
                                &lt;label for=&quot;doors&quot; class=&quot;block text-sm font-medium leading-5 text-neutral-200&quot;&gt;Doors&lt;&#x2F;label&gt;
                                &lt;input type=&quot;number&quot; min=&quot;3&quot; max=&quot;100&quot; placeholder=&quot;3&quot; value=&quot;3&quot; id=&quot;doors&quot; class=&quot;mt-1 form-input block w-full py-2 px-3 border border-neutral-600 rounded-md shadow-sm focus:outline-none focus:shadow-outline focus:border-primary-300 transition duration-150 ease-in-out sm:text-sm sm:leading-5&quot; &#x2F;&gt;
                            &lt;&#x2F;div&gt;
                            &lt;div class=&quot;col-span-3&quot;&gt;
                                &lt;label for=&quot;tries&quot; class=&quot;block text-sm font-medium leading-5 text-neutral-200&quot;&gt;Tries&lt;&#x2F;label&gt;
                                &lt;input type=&quot;number&quot; min=&quot;1&quot; max=&quot;100000&quot; value=&quot;1000&quot; placeholder=&quot;1000&quot; id=&quot;tries&quot; class=&quot;mt-1 form-input block w-full py-2 px-3 border border-neutral-600 rounded-md shadow-sm focus:outline-none focus:shadow-outline focus:border-primary-300 transition duration-150 ease-in-out sm:text-sm sm:leading-5&quot; &#x2F;&gt;
                            &lt;&#x2F;div&gt;
                        &lt;&#x2F;div&gt;
                    &lt;&#x2F;div&gt;
                    &lt;div class=&quot;px-4 py-3 bg-primary-800 text-right sm:px-6&quot;&gt;
                        &lt;button id=&quot;calcButton&quot; class=&quot;py-2 px-4 border border-transparent text-sm leading-5 font-medium rounded-md text-neutral-950 bg-primary-300 shadow-sm hover:bg-primary-200 focus:outline-none focus:shadow-outline active:bg-primary-400 transition duration-150 ease-in-out&quot; &gt;
                            calculate
                        &lt;&#x2F;button&gt;
                    &lt;&#x2F;div&gt;
                &lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;source-code&quot;&gt;Source code&lt;&#x2F;h2&gt;
&lt;p&gt;Here is the JavaScript code for the calculation. Alternatively you can look at the page source:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Play a game&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; play&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;doors&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; carDoor&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; Math&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;floor&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;Math&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;random&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; doors&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; selectedDoor&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; Math&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;floor&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;Math&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;random&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; doors&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; switchDoor&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; carDoor&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; ===&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; selectedDoor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;    ?&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;carDoor&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; %&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; doors&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Door with goat&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;    :&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; carDoor&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt;    keepWin&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; selectedDoor&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; ===&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; carDoor&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt;    switchWin&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; switchDoor&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; ===&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; carDoor&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;  }&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Simulate some games&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; simulate&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;doors&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt; tries&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; result&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;...&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; Array&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;tries&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;map&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; play&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;doors&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;reduce&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;agg&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt; curr&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;      if&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;curr&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;keepWin&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; agg&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;keepWins&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;      if&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;curr&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;switchWin&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; agg&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;switchWins&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;      return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; agg&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;    }&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt; keepWins&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt; switchWins&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt;    winPercentKeep&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; result&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;keepWins&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; tries&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-object z-member&quot;&gt;    winPercentSwitch&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; result&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;switchWins&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; tries&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;  }&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Example output for 1,000 tries with 3 doors&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;console&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;simulate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1000&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;observations&quot;&gt;Observations&lt;&#x2F;h2&gt;
&lt;p&gt;If you&#x27;ve read so far, you might have realized something and asked: &quot;Hey, wait a minute, what are you doing there?&quot;
The algorithm for selecting the &quot;switch-to&quot; door directly uses the conclusion.
Yes, that&#x27;s true: when you try to implement an efficient selection mechanism,
you should find that the &quot;switch-to&quot; door has to be the door with the dream car in all the cases where the
contestant has initially chosen a door with a goat behind it. That happens in 2&#x2F;3 of all cases.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;further-reading&quot;&gt;Further reading&lt;&#x2F;h2&gt;
&lt;p&gt;Read more about the problem on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Monty_Hall_problem&quot;&gt;Wikipedia&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;script src=&quot;resources&#x2F;js&#x2F;monty-hall-problem.js&quot; integrity=&quot;sha384-6EJqBhC&#x2F;op0PripAiuR7toTQK2jkAqjVGerf0GCXn8XjlCmRoLPFEavyvodRNN+D&quot;&gt;&lt;&#x2F;script&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The pandemic is not a great leveller</title>
        <published>2020-04-12T00:00:00+00:00</published>
        <updated>2020-04-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/great-leveller/"/>
        <id>https://weitzel.dev/blog/great-leveller/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/great-leveller/">&lt;h2 id=&quot;the-quote&quot;&gt;The quote&lt;&#x2F;h2&gt;
&lt;p&gt;BBC presenter Emily Maitlis, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;L6wIcpdJyCI&quot;&gt;April 8th, 2020&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The language around Covid-19 has sometimes felt trite and misleading.
You do not survive the illness through fortitude and strength of character,
whatever the Prime Minister&#x27;s colleagues will tell us.
And the disease is not &#x27;a great leveller&#x27;, the consequences of which everyone, rich or poor, suffers the same.
This is a myth which needs debunking.&lt;&#x2F;p&gt;
&lt;p&gt;Those serving on the front line right now, bus drivers and shelf stackers, nurses, care home workers,
hospital staff and shopkeepers are disproportionately the lower paid members of our workforce.
They are more likely to catch the disease, because they are more exposed.
Those who live in tower blocks and small flats will find the lockdown tougher.
Those in manual jobs will be unable to work from home.&lt;&#x2F;p&gt;
&lt;p&gt;This is a health issue with huge ramifications for social welfare,
and it&#x27;s a welfare issue with huge ramifications for public health.
Tonight, as France goes into recession,
and the World Trade Organisation warns the pandemic could provoke the deepest economic downturn of our lifetimes,
we ask what kind of social settlement might need to be put in place to stop the inequality becoming even more stark.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;my-opinion&quot;&gt;My opinion&lt;&#x2F;h2&gt;
&lt;p&gt;We have to decide whether there should be a basic right to housing, social participation and a basic income.
We have to decide whether obscene wealth and incomes should be abolished worldwide through taxation.
It is not because of money or possibilities, there is no political will at the moment.
The time will come when we will have no choice, or we&#x27;ll lose our democracy.
We then will repeat the painful processes that brought us democracy.
Do we want that?&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Terms</title>
        <published>2020-01-08T00:00:00+00:00</published>
        <updated>2020-01-08T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/pages/terms/"/>
        <id>https://weitzel.dev/pages/terms/</id>
        
        <content type="html" xml:base="https://weitzel.dev/pages/terms/">&lt;p&gt;&lt;em&gt;Last updated: February 9, 2026&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;general-character-of-the-website&quot;&gt;General character of the website&lt;&#x2F;h2&gt;
&lt;p&gt;This website is a &lt;strong&gt;private, non-commercial blog&lt;&#x2F;strong&gt; with mostly informational content. It can be used &lt;strong&gt;without registration&lt;&#x2F;strong&gt;
and &lt;strong&gt;without providing personal data&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The following notes are for transparency and clarity. They are &lt;strong&gt;not general terms and conditions&lt;&#x2F;strong&gt; and &lt;strong&gt;not a contract&lt;&#x2F;strong&gt;
in a legal sense.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;content-and-opinions&quot;&gt;Content and opinions&lt;&#x2F;h2&gt;
&lt;p&gt;The content published on this website reflects &lt;strong&gt;my personal views and experiences&lt;&#x2F;strong&gt;. It is &lt;strong&gt;not professional advice&lt;&#x2F;strong&gt;,
in particular not legal, tax, medical, or financial advice.&lt;&#x2F;p&gt;
&lt;p&gt;I aim to provide correct and current information but make &lt;strong&gt;no warranties&lt;&#x2F;strong&gt; regarding accuracy, completeness, or suitability
for a specific purpose.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;liability&quot;&gt;Liability&lt;&#x2F;h2&gt;
&lt;p&gt;Liability for damages resulting from the use or non-use of the information provided on this website is excluded,
&lt;strong&gt;unless caused by intent or gross negligence&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Mandatory statutory liability remains unaffected, especially for injury to life, body, or health.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;external-links&quot;&gt;External links&lt;&#x2F;h2&gt;
&lt;p&gt;This website may contain links to external websites of third parties. I have no influence on their content.&lt;&#x2F;p&gt;
&lt;p&gt;The provider or operator of the linked pages is always responsible. At the time of linking, no illegal content was apparent.
If legal violations become known, the links will be removed promptly.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;copyright-and-use-of-content&quot;&gt;Copyright and use of content&lt;&#x2F;h2&gt;
&lt;p&gt;The content and works published on this website are subject to German copyright law.&lt;&#x2F;p&gt;
&lt;p&gt;Unless stated otherwise, &lt;strong&gt;copying and redistribution&lt;&#x2F;strong&gt; are permitted &lt;strong&gt;as long as the author&#x27;s attribution notice remains&lt;&#x2F;strong&gt; and the use is not commercial.&lt;&#x2F;p&gt;
&lt;p&gt;Any further use requires my prior consent.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;privacy&quot;&gt;Privacy&lt;&#x2F;h2&gt;
&lt;p&gt;Information about the processing of personal data and browser storage can be found in the
&lt;a href=&quot;https:&#x2F;&#x2F;weitzel.dev&#x2F;pages&#x2F;privacy&#x2F;&quot;&gt;privacy policy&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;applicable-law&quot;&gt;Applicable law&lt;&#x2F;h2&gt;
&lt;p&gt;These notes and the use of this website are governed by the laws of the Federal Republic of Germany.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;closing-note&quot;&gt;Closing note&lt;&#x2F;h2&gt;
&lt;p&gt;If any part of these notes is or becomes invalid, the remaining content remains effective.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Anatomy of problem-solving</title>
        <published>2019-07-14T00:00:00+00:00</published>
        <updated>2019-07-14T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/anatomy-of-problem-solving/"/>
        <id>https://weitzel.dev/blog/anatomy-of-problem-solving/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/anatomy-of-problem-solving/">&lt;p&gt;We are software developers and solving problems is what we do.
But how do we do it? And what is a problem? What are the constraints?&lt;&#x2F;p&gt;
&lt;p&gt;We have to first understand the problem in order to be able to solve it.
While this seems obvious, it often does not happen.
We see so many flawed solutions because a problem or requirement was not understood correctly.
Spending time to really understand the problem may not sound productive - we could be coding already.
But the price to pay for the wrong start will be high.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;understand&quot;&gt;Understand&lt;&#x2F;h2&gt;
&lt;p&gt;Most of the time, we solve someone else&#x27;s problems.
We call her &lt;em&gt;the customer&lt;&#x2F;em&gt;.
In most cases she is not a software developer.
So a problem is translated from the business domain into the technical domain where it should be solved.
A lot can be lost during this process.
Just be aware that the customer normally knows the business domain better than you, so she can give you the most valuable feedback.
Talk to her as often as you can and explain the problem back to her.
At the same time, pay attention to whether all use-cases are covered.
Customers tend to concentrate on the most common aspects.
When you hear: &quot;Normally, we do it like this&quot;, this a sure sign that not all cases are covered.&lt;&#x2F;p&gt;
&lt;p&gt;Don&#x27;t start coding before at least the following questions are answered with a &quot;yes&quot;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;is the specification clear enough?&lt;&#x2F;li&gt;
&lt;li&gt;do you know what goals should be reached?&lt;&#x2F;li&gt;
&lt;li&gt;can you prioritize the elements of the solution?&lt;&#x2F;li&gt;
&lt;li&gt;do you understand the constraints?&lt;&#x2F;li&gt;
&lt;li&gt;do you understand the data?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;plan&quot;&gt;Plan&lt;&#x2F;h2&gt;
&lt;p&gt;Coming up with a plan requires good ideas and analytic skills.
This is where it gets tricky: there&#x27;s no one-size-fits-all solution to a working plan.
But here are a few hints:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;use your knowledge from prior experiences&lt;&#x2F;li&gt;
&lt;li&gt;how have others solved similar problems?&lt;&#x2F;li&gt;
&lt;li&gt;use &lt;em&gt;divide and conquer&lt;&#x2F;em&gt; to break down a problem into a set of smaller ones&lt;&#x2F;li&gt;
&lt;li&gt;simplify if possible; generalization&#x2F;abstraction can be simplification&lt;&#x2F;li&gt;
&lt;li&gt;don&#x27;t try to optimize prematurely&lt;&#x2F;li&gt;
&lt;li&gt;if you do not make progress, try to work backwards from the output (solution) to the data (problem)&lt;&#x2F;li&gt;
&lt;li&gt;if you&#x27;re stuck, don&#x27;t rush it!&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;execute&quot;&gt;Execute&lt;&#x2F;h2&gt;
&lt;p&gt;You have failed if you build a tall tower and it collapses while you put in the last stone - in fact any stone.
That&#x27;s why you always have to make sure that what you have built so far can carry the weight of the rest, and much more.
Unit tests, integration tests, system tests, and end-to-end tests to the rescue - but mostly unit tests.&lt;&#x2F;p&gt;
&lt;p&gt;Pay attention that your foundations are strong.
If you build on shaky ground, the project might be doomed from the start.
Is there anything you have to evaluate first, like concepts or libraries, to know the risks involved in using them?&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;work top-down&lt;br&#x2F;&gt;
Start with the overall structure&#x2F;architecture before digging into the details.&lt;&#x2F;li&gt;
&lt;li&gt;prioritize the most important aspects and the ones with the highest risks&lt;br&#x2F;&gt;
That way you run into the hard problems first. If you have to change course, there&#x27;s only some amount of work lost.&lt;&#x2F;li&gt;
&lt;li&gt;break and organize dependencies&lt;br&#x2F;&gt;
Have you read &lt;em&gt;Clean Code&lt;&#x2F;em&gt; from Robert C. Martin (462 pages, from 2008)?
Decouple as much as you can, it will make testing much easier.&lt;&#x2F;li&gt;
&lt;li&gt;put fragments together as early as possible&lt;br&#x2F;&gt;
The earlier all developers working on one project get feedback on how their components behave within the system, the better it will be.&lt;&#x2F;li&gt;
&lt;li&gt;write unit tests as if your life depends on it&lt;br&#x2F;&gt;
Because ... it might. Bugs that are found in production might have the most severe consequences.
Management that fails to understand that and does not enforce it - because there is e.g. not enough time - is incompetent.&lt;&#x2F;li&gt;
&lt;li&gt;treat documentation as a first-class citizen&lt;br&#x2F;&gt;
As a developer, don&#x27;t write documentation that repeats what you can already see in the code.
Focus on describing intent instead.
There will always be some overlap, but at least try hard enough.&lt;&#x2F;li&gt;
&lt;li&gt;make your code easy to read and understand&lt;br&#x2F;&gt;
We spend an order of magnitude more time reading code than writing it.
So please absolutely no &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Code_golf&quot;&gt;Code Golf&lt;&#x2F;a&gt;.
You want to easily understand your own code many weeks after you wrote it. The same is true for someone else who&#x27;s reading it for the first time.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote class=&quot;hippo&quot;&gt;
&quot;If I had more time, I would have written a shorter letter&quot;.&lt;br&gt;
-- Blaise Pascal&lt;br&gt;
(also attributed to Mark Twain)&lt;br&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Yeah Hip, that&#x27;s really a good summary of the last point: put more effort into writing something, so that you don&#x27;t steal your reader&#x27;s time.
If you can help him understand more quickly or easily, by all means, do it!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-small-example&quot;&gt;A small example&lt;&#x2F;h2&gt;
&lt;p&gt;The following artificial example will cover only a small, selected sample from the topics mentioned above.
It has a very narrow scope, but even then I cannot cover every aspect without making this post overly long.
So I won&#x27;t. All code will be in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;golang.org&#x2F;&quot;&gt;Go&lt;&#x2F;a&gt;. Here it goes:&lt;&#x2F;p&gt;
&lt;p&gt;You have a vector of non-negative integer values sorted in ascending order and a positive integer value &lt;code&gt;d&lt;&#x2F;code&gt; not greater than 20.
The vector might contain duplicate values and contains not more than 10,000 elements. No element is greater than 20,000.
&lt;b&gt;How many tuples &lt;code&gt;(a, b, c)&lt;&#x2F;code&gt; of 3 elements from this vector can be formed where &lt;code&gt;c - b == b - a == d&lt;&#x2F;code&gt;?&lt;&#x2F;b&gt;
This implies that &lt;code&gt;a &amp;lt; b &amp;lt; c&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Example: if the distance &lt;code&gt;d&lt;&#x2F;code&gt; is 2 and the vector is &lt;code&gt;[1, 2, 3, 4, 5, 6]&lt;&#x2F;code&gt;, the tuples &lt;code&gt;(1, 3, 5)&lt;&#x2F;code&gt; and &lt;code&gt;(2, 4, 6)&lt;&#x2F;code&gt; satisfy the requirement.
These two tuples are the only ones, so the answer would be &lt;code&gt;2&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;See the HackerRank problem &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.hackerrank.com&#x2F;challenges&#x2F;beautiful-triplets&#x2F;problem&quot;&gt;Beautiful Triplets&lt;&#x2F;a&gt; for details.
Duplicate values are allowed here, which is (officially) not allowed in the specification on HackerRank -
but they break their own specs by having at least one test case that uses duplicates and checks that (test case 10 for the Go language).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;understand-1&quot;&gt;Understand?&lt;&#x2F;h3&gt;
&lt;p&gt;The specification seems easy enough, and since it has been on HackerRank for a couple of years, they should have had all the time needed for adding missing information, right?
But still, is there anything that is unclear to you? Check the questions from the checklist above. The nature of the questions is not only technical.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;plan-1&quot;&gt;Plan?&lt;&#x2F;h3&gt;
&lt;p&gt;Since only basic data types and calculations are involved, you devise a plan to solve the problem head on:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;initialize a &lt;code&gt;counter&lt;&#x2F;code&gt; to 0&lt;&#x2F;li&gt;
&lt;li&gt;from the left of the vector, take the next element (has value &lt;code&gt;e&lt;&#x2F;code&gt;, that&#x27;s the first one initially), go to step 6 if there&#x27;s no next element&lt;&#x2F;li&gt;
&lt;li&gt;check the rest of the vector if you find &lt;code&gt;e + d&lt;&#x2F;code&gt;, if not: continue with step 2&lt;&#x2F;li&gt;
&lt;li&gt;from the position where you found &lt;code&gt;e + d&lt;&#x2F;code&gt;, check the rest of the vector if you find &lt;code&gt;e + 2*d&lt;&#x2F;code&gt;, if not: continue with step 2&lt;&#x2F;li&gt;
&lt;li&gt;we have a match: increment counter by 1 and go to step 2&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;counter&lt;&#x2F;code&gt; holds the answer&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;execute-1&quot;&gt;Execute?&lt;&#x2F;h3&gt;
&lt;p&gt;You implement the solution from the plan and follow all the points:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;break and organize dependencies: all functions are pure functions except for input and output (side effects). But you still make them easily testable by using interfaces where possible.&lt;&#x2F;li&gt;
&lt;li&gt;write unit tests: you have reached 100% code coverage except for the &lt;code&gt;main&lt;&#x2F;code&gt; function that wires everything together - including the specific values for in- and output locations.&lt;&#x2F;li&gt;
&lt;li&gt;treat documentation as a first-class citizen: you document every function and add the occasional additional comment in the body of some functions.&lt;&#x2F;li&gt;
&lt;li&gt;make your code easy to read and understand: where necessary you resist the urge to use single letter variable names, even though this is considered idiomatic in Go.
You even do a code review with a colleague to check if he understands the code and has suggestions for improvements.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;what-happens-next&quot;&gt;What happens next&lt;&#x2F;h3&gt;
&lt;p&gt;Before merging the code into the &lt;code&gt;develop&lt;&#x2F;code&gt; branch in the Git repository, you recognize that you&#x27;ve missed a test for duplicate values.
You write it, it fails.
Of course it fails, you have not included it in the plan!
What has to change so that the test passes?&lt;&#x2F;p&gt;
&lt;p&gt;Ok, you get it: while searching for &lt;code&gt;e + d&lt;&#x2F;code&gt; and &lt;code&gt;e + 2*d&lt;&#x2F;code&gt; you should not stop, but you have to count how often they both occur (initially you have not thought about that).
Example: &lt;code&gt;[1, 3, 3, 5, 5]&lt;&#x2F;code&gt; with &lt;code&gt;d == 2&lt;&#x2F;code&gt; should lead to the answer &lt;code&gt;4&lt;&#x2F;code&gt; - accounting for every possible combination of the elements.
So in steps 3 and 4 you establish a counter for &lt;code&gt;e + d&lt;&#x2F;code&gt; (call it &lt;code&gt;countD1&lt;&#x2F;code&gt;) and &lt;code&gt;e + 2*d&lt;&#x2F;code&gt; (&lt;code&gt;countD2&lt;&#x2F;code&gt;) each.
In step 5 you increment the tuple-counter by the product from the other counters: &lt;code&gt;counter += countD1 * countD2&lt;&#x2F;code&gt;, thereby accounting for all possibilities.&lt;&#x2F;p&gt;
&lt;p&gt;You change the implementation according to the revised plan, and the test passes. Well, time to commit again and merge into &lt;code&gt;develop&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Some time passes and you do other work. Eventually, &lt;code&gt;develop&lt;&#x2F;code&gt; is merged into &lt;code&gt;master&lt;&#x2F;code&gt; by the lead developer.
A little later a release branch is created, and off it goes to production.
Not shortly after, a bug report comes in: the program hangs.
Because your software uses metrics, your team can quickly identify the culprit: it&#x27;s your implementation from above.
What? All tests were OK and you cannot believe that it can hang.&lt;&#x2F;p&gt;
&lt;p&gt;After further investigation, your team finds out that someone was feeding a vector of 9,800 elements to your code.
It did not hang, it simply did not provide the answer within a couple of minutes.
Only 9,800 elements and it takes that much time?&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s the point where you start remembering Big O notation that describes an upper bound for the performance&#x2F;complexity of an algorithm.
After looking at your code, you recognize three nested loops:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;first loop iterates over the vector, taking each element&lt;&#x2F;li&gt;
&lt;li&gt;the second loop iterates over the rest of the vector trying to find &lt;code&gt;e + d&lt;&#x2F;code&gt;, it stops if an element is greater than &lt;code&gt;e + d&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;the third loop iterates over the rest of the vector that&#x27;s left after &lt;code&gt;e + d&lt;&#x2F;code&gt; is found, trying to find &lt;code&gt;e + 2*d&lt;&#x2F;code&gt; (it stops, too)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You now quickly realize that your solution has on upper bound of $\mathcal{O}\left(n^{3}\right)$.
For a vector of 9,800 elements, that&#x27;s approx. $10^{12}$. Wow!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;rethinking-the-solution&quot;&gt;Rethinking the solution&lt;&#x2F;h3&gt;
&lt;p&gt;Even though your solution works in theory, it&#x27;s not usable for vectors beyond more than a couple of elements.
You have to come up with another solution! So you start thinking.&lt;&#x2F;p&gt;
&lt;p&gt;If you have an element &lt;code&gt;e&lt;&#x2F;code&gt;, can you quickly find out if elements &lt;code&gt;e + d&lt;&#x2F;code&gt; and &lt;code&gt;e + 2*d&lt;&#x2F;code&gt; are present in the vector?
Not if you only have a vector.
But if you had a dictionary where you could look up &lt;code&gt;e + d&lt;&#x2F;code&gt; and &lt;code&gt;e + 2*d&lt;&#x2F;code&gt; it would be easy.&lt;&#x2F;p&gt;
&lt;p&gt;So you decide to break the problem down into two parts:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;create a dictionary (hash-map), with each element as the key, and how often it occurs in the vector as the value&lt;&#x2F;li&gt;
&lt;li&gt;iterate over the vector (current element is &lt;code&gt;e&lt;&#x2F;code&gt;) and look up each element &lt;code&gt;e + d&lt;&#x2F;code&gt;, and &lt;code&gt;e + 2*d&lt;&#x2F;code&gt;, how often it occurs
&lt;ul&gt;
&lt;li&gt;multiply the counts to account for all combinations&lt;&#x2F;li&gt;
&lt;li&gt;add the products over the counts of &lt;code&gt;e + d&lt;&#x2F;code&gt; and &lt;code&gt;e + 2*d&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This solution requires two passes over the vector: one to build the dictionary, and another to calculate the final count.
After the experience with your first solution, you want to make sure that you have a really good algorithm.
You think a little harder.&lt;&#x2F;p&gt;
&lt;p&gt;It occurs to you, that you can solve the problem with only one pass over the vector.
How?
Since the vector is sorted in ascending order, you would have processed &lt;code&gt;e&lt;&#x2F;code&gt; and &lt;code&gt;e + d&lt;&#x2F;code&gt; already when you reach &lt;code&gt;e + 2*d&lt;&#x2F;code&gt;.
So you decide to look backward:
for each element, you look for &lt;code&gt;e - d&lt;&#x2F;code&gt; and &lt;code&gt;e - 2*d&lt;&#x2F;code&gt; instead, multiply the frequency count, update the dictionary for the current element &lt;code&gt;e&lt;&#x2F;code&gt; by incrementing its frequency count, and adding it all together.
Thereby the dictionary is created while you iterate over the vector, not in a separate step.
Both new solutions have a complexity of $\mathcal{O}\left(n\right)$.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;final-solution&quot;&gt;Final solution&lt;&#x2F;h3&gt;
&lt;p&gt;After implementing all necessary changes and adding tests with generated vectors up to 10,000 elements, you merge the following code into &lt;code&gt;develop&lt;&#x2F;code&gt;.
This was 2 years ago and you have not heard from it ever again.
But today, you decide to revisit it while &quot;on-boarding&quot; a new developer for the team.
He does &lt;em&gt;not&lt;&#x2F;em&gt; understand the code immediately, but it does not take that long either.
So you give him his first task: improve the code&#x2F;the documentation so that it would have been easier for him.
He just went through the experience and should come up with some ideas, right?&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;package&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;	&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-entity z-name z-import&quot;&gt;fmt&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;	&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-entity z-name z-import&quot;&gt;io&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;	&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-entity z-name z-import&quot;&gt;os&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; beautifulTriplets calculates the number of 3-element tuples in array a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; where each element has the same distance d from the middle element.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; the array a is in ascending order.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; beautifulTriplets&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;d&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt; a&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;	countTriplets&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;	frequency&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; make&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;	for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; _&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; range&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; a&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;		countD1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; hasD1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; frequency&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;d&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;		countD2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; hasD2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; frequency&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;d&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;		if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; hasD1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; hasD2&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;			&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; all combinations if there are duplicates&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;			countTriplets&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; countD1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; countD2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;		frequency&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;	return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; countTriplets&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;	in&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; out&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;Stdin&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;Stdout&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;	d&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; readInput&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;in&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;	result&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; beautifulTriplets&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;d&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; a&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;	writeOutput&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;out&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; result&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; readInput reads the inputs from the reader.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; returns the distance d and an array that has ascending order.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; readInput&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;reader&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; io&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Reader&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;	var&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;	fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Fscan&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;reader&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;d&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;	a&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; make&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;	for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;		fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Fscan&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;reader&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;	return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; d&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; writeOutput writes the outputs to the writer.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; writeOutput&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;writer&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; io&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Writer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt; result&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;	fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Fprintln&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;writer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; result&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We all want to write good software, but sometimes that&#x27;s not enough.
If you know how to do it, and you want to do it, your success still depends on factors you cannot control.
Inside those limits you should do the best work possible.
Nobody should honestly expect what&#x27;s not possible.
I will end this post with a quote found on Twitter.&lt;&#x2F;p&gt;
&lt;figure class=&quot;mt-4&quot;&gt;&lt;span class=&quot;light-dark-image inline-block&quot;&gt;
      &lt;img class=&quot;block image-shortcode&quot; src=&quot;https:&#x2F;&#x2F;weitzel.dev&#x2F;blog&#x2F;anatomy-of-problem-solving&#x2F;resources&#x2F;media&#x2F;sarah-mei-awful-code-light.webp&quot; alt=&quot;Sarah Mei Twitter Post&quot; width=&quot;500&quot; height=&quot;139&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
      &lt;img class=&quot;block image-shortcode&quot; src=&quot;https:&#x2F;&#x2F;weitzel.dev&#x2F;blog&#x2F;anatomy-of-problem-solving&#x2F;resources&#x2F;media&#x2F;sarah-mei-awful-code-dark.webp&quot; alt=&quot;Sarah Mei Twitter Post&quot; width=&quot;500&quot; height=&quot;139&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
    &lt;&#x2F;span&gt;
&lt;&#x2F;figure&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Cumulative standard normal distribution</title>
        <published>2019-07-07T00:00:00+00:00</published>
        <updated>2019-07-07T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/cumulative-standard-normal-distribution/"/>
        <id>https://weitzel.dev/blog/cumulative-standard-normal-distribution/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/cumulative-standard-normal-distribution/">&lt;p&gt;I&#x27;ve written about the use of the central limit theorem (CLT) to solve some problems in statistics &lt;a href=&quot;https:&#x2F;&#x2F;weitzel.dev&#x2F;blog&#x2F;statistics-challenge&#x2F;&quot;&gt;before&lt;&#x2F;a&gt;.
It involves calculating a z-value and looking up the probability in a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Standard_normal_table&quot;&gt;z-table&lt;&#x2F;a&gt;.
A z-table holds the cumulative probabilities for values that follow the standard normal distribution, i.e. the mean is 0 and the standard deviation is 1.
For other means and standard deviations, the values can be normalized, so that mean&#x2F;standard deviation of the standard normal distribution apply.&lt;&#x2F;p&gt;
&lt;p&gt;In programs like Excel or in code, we can easily calculate the z-table values.
Some languages like
Java (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;commons.apache.org&#x2F;proper&#x2F;commons-math&#x2F;javadocs&#x2F;api-3.6.1&#x2F;org&#x2F;apache&#x2F;commons&#x2F;math3&#x2F;special&#x2F;Erf.html&quot;&gt;Apache Commons Math&lt;&#x2F;a&gt;) or
Rust (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;libm&#x2F;latest&#x2F;libm&#x2F;fn.erf.html&quot;&gt;libm crate&lt;&#x2F;a&gt;)
require the use of 3rd party libraries if you don&#x27;t want to do all the work yourself, but Go has everything built-in already.
Let&#x27;s see how to do it.&lt;&#x2F;p&gt;
&lt;p&gt;The cumulative distribution function for a function with normal distribution:
$$\phi\left(x\right) = \frac{1}{2}\left(1+\textbf{erf}\left(\frac{x-\mu}{\sigma\sqrt{2}}\right)\right)$$&lt;&#x2F;p&gt;
&lt;p&gt;Where $\textbf{erf}$ is the error function:
$$\textbf{erf}\left(z\right) = \frac{2}{\sqrt{\pi}}\int_0^z e^{-t^2} dt$$&lt;&#x2F;p&gt;
&lt;p&gt;Go has the error function $\textbf{erf}$ in the &lt;code&gt;math&lt;&#x2F;code&gt; package, so it&#x27;s easy to write $\phi(x)$ as a higher-order-function, that takes the mean $\mu$ and the standard deviation $\sigma$ and gives us a function that only depends on the random variable &lt;code&gt;x&lt;&#x2F;code&gt;.
With this we can write all the code necessary to solve the statistics problem mentioned above.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;package&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;	&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-entity z-name z-import&quot;&gt;fmt&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;	&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-entity z-name z-import&quot;&gt;math&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; phi&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;m&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; float64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt; sd&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; float64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;float64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; float64&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;	return&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;x&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; float64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; float64&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;		z&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; m&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; sd&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; math&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Sqrt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;		return&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; math&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Erf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;z&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;	maxWeight&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; boxes&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; m&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; sd&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 2630&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 36&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 72&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; the central limit theorem states that if we have a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; sufficiently large sample of n boxes, we can expect&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; the mean of this sample to be equal to the statistical&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; mean, and the σ_sample of the sample to be σ &#x2F; sqrt(n)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;	zTable&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; phi&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; cumulative std. normal distribution&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;	boxCritical&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; maxWeight&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; boxes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;	sdSample&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; sd&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; math&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Sqrt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;boxes&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; normalize for z-table use&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;	z&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;boxCritical&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; m&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; sdSample&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;	p&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; zTable&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;z&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; probability that boxes can be transported&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;	fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-placeholder z-constant z-other&quot;&gt;%f&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; p&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Rust has only a minimal standard library by design, where the error function is not included.
But you can use the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;libm&#x2F;latest&#x2F;libm&#x2F;fn.erf.html&quot;&gt;libm crate&lt;&#x2F;a&gt; for that.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; libm&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;erf&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; phi&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;m&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; f64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; sd&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; f64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; Fn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;f64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; f64&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    move&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; erf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; m&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; sd&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 2_&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;f64&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;sqrt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; max_weight&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; f64&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 2630&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; in kg&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; boxes&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;      :&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; f64&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;   36&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; amount of boxes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; m&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;          :&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; f64&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;   72&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; mean of the historic boxes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; sd&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;         :&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; f64&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;    3&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; standard distribution of the historic boxes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; z_table&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; phi&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;   &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; cumulative std. normal distribution&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; box_critical&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; max_weight&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; boxes&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; sd_sample&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; sd&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; boxes&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;sqrt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; normalize for z-table use&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; z&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;box_critical&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; m&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; sd_sample&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; p&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; z_table&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;z&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; probability that boxes can be transported&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; p&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We could have used the $\phi$ function without normalizing, since it can handle arbitrary means and standard deviations, but I wanted to show a way that mimics how you would do it by hand using a z-table.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Tail recursion with trampoline in Go</title>
        <published>2019-07-06T00:00:00+00:00</published>
        <updated>2019-07-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/golang-trampoline/"/>
        <id>https://weitzel.dev/blog/golang-trampoline/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/golang-trampoline/">&lt;p&gt;The Go compiler is another example for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;golang&#x2F;go&#x2F;issues&#x2F;22624&quot;&gt;missing support&lt;&#x2F;a&gt; for proper tail call optimization.
It&#x27;s a deliberate choice: reusing and thereby overwriting the current stack frame with the next one deletes all information needed to provide a meaningful stacktrace in the case of an error.
This is one of the reasons that Go does not support it.
See my &lt;a href=&quot;https:&#x2F;&#x2F;weitzel.dev&#x2F;blog&#x2F;tail-recursion-with-trampoline&#x2F;&quot;&gt;previous post&lt;&#x2F;a&gt; on the topic of using the trampoline device in JavaScript for a more general discussion.&lt;&#x2F;p&gt;
&lt;p&gt;The following example shows you how to use the trampoline device in Go.
We will implement the famous Fibonacci numbers this way.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-go-type-system&quot;&gt;The Go type system&lt;&#x2F;h2&gt;
&lt;p&gt;Since Go is a statically typed language, every function, parameter, variable, etc. has to have a type at compile time.
Go has no generics either, which makes it more verbose, because generics allow you to abstract the same algorithm over multiple data types.
That&#x27;s why you cannot write a trampoline device in Go that is applicable for all function signatures like in JavaScript.
Well, maybe you could by using reflection, but that is not considered idiomatic for the language.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-solution&quot;&gt;The solution&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;ll walk backwards: the call to the function should look like this: &lt;code&gt;fib(10)&lt;&#x2F;code&gt;. We expect the result &lt;code&gt;55&lt;&#x2F;code&gt;.
So the type of this function is &lt;code&gt;func(int) int&lt;&#x2F;code&gt;, a function that expects an int-argument and returns a int.
It follows, that this is the type of the return value of the &lt;code&gt;trampoline&lt;&#x2F;code&gt; function.&lt;&#x2F;p&gt;
&lt;p&gt;We know that we have to call the &lt;code&gt;trampoline&lt;&#x2F;code&gt; function with the thunking version of the function that produces the Fibonacci numbers.&lt;&#x2F;p&gt;
&lt;p&gt;The signature of this thunking version is simple.
We have to supply all the parameters and aggregator values and expect either a result of type &lt;code&gt;int&lt;&#x2F;code&gt; or a function with no parameters at all, that returns either the result or another function with no parameters.
Let&#x27;s call this last recursive function type &lt;code&gt;thunkType&lt;&#x2F;code&gt; and define it: &lt;code&gt;type thunkType func() (int, thunkType)&lt;&#x2F;code&gt;.
So the return type of the &lt;code&gt;thunkFib&lt;&#x2F;code&gt; function is a tuple: &lt;code&gt;(int, thunkType)&lt;&#x2F;code&gt;.
The parameters are &lt;code&gt;n int&lt;&#x2F;code&gt; for the argument proper, and the two aggregators &lt;code&gt;prev&lt;&#x2F;code&gt; and &lt;code&gt;curr&lt;&#x2F;code&gt; (starting with &lt;code&gt;0&lt;&#x2F;code&gt; and &lt;code&gt;1&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;The last thing we need is a function inside of &lt;code&gt;thunkFib&lt;&#x2F;code&gt; that wraps all the parameters in a function with no arguments and returns a tuple - either the final result or another &lt;code&gt;thunkType&lt;&#x2F;code&gt;.
Let&#x27;s define its own type: &lt;code&gt;type fnType func(int, int, int) (int, thunkType)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now we&#x27;re ready to write this wrapper function &lt;code&gt;thunk&lt;&#x2F;code&gt; and use it inside our &lt;code&gt;thunkFib&lt;&#x2F;code&gt; function.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;package&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;	&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-entity z-name z-import&quot;&gt;fmt&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; parameters are n, prev, and current&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; return either the result (int) or a thunkType if not done&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; fnType&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; thunkType&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; return either the result (int) or another thunk&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; thunkType&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; thunkType&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; thunk&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; fnType&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt; prev&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt; curr&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; thunkType&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;	return&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; thunkType&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;		return&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; prev&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; curr&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; thunkFib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt; prev&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt; curr&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; thunkType&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;	if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;		return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; prev&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-language&quot;&gt; nil&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;	if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;		return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; curr&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-language&quot;&gt; nil&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; since we return another thunk, the int result does not matter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;	return&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; &#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; unused &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; thunk&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;thunkFib&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; curr&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; curr&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;prev&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; trampoline&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; fnType&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;	return&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;		result&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; f&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; initial values for aggregators&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;		for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;			if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; f&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-language&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;				break&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;			result&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; f&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; f&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;		return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; result&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;	n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 10&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; fib(10) == 55&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;	fib&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; trampoline&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;thunkFib&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;	fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Fibonacci(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-placeholder z-constant z-other&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;) = &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-placeholder z-constant z-other&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; fib&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Tail recursion with trampoline</title>
        <published>2019-03-16T00:00:00+00:00</published>
        <updated>2019-03-16T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/tail-recursion-with-trampoline/"/>
        <id>https://weitzel.dev/blog/tail-recursion-with-trampoline/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/tail-recursion-with-trampoline/">&lt;p&gt;In case your platform lacks support for proper tail call optimization and you want to do functional programming, you might run into stack space problems.
This can be mitigated, but you have to find a way yourself to make it work.
The specific platform I&#x27;m writing about here is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nodejs.org&#x2F;en&#x2F;about&quot;&gt;Node.js&lt;&#x2F;a&gt;.
After a little introduction, I show one well-known solution to the problem.&lt;&#x2F;p&gt;
&lt;p&gt;In functional programming, recursion is a fundamental concept for handling mutability.
Pure functional languages like Haskell do not allow mutation of variables, so you have to come up with a different solution to the problem.
What you do is called &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;alvinalexander.com&#x2F;scala&#x2F;functional-programming-simplified-book&quot;&gt;update as you copy&lt;&#x2F;a&gt;.
You create new variables by calculating their values from the values of existing ones.
But you never assign a new value to a variable that already has one.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;recursion&quot;&gt;Recursion&lt;&#x2F;h2&gt;
&lt;p&gt;To simplify the reasoning, I will assume that a function does not rely on or modify external state, i.e. values of variables outside of its body.
Math is organized this way: &lt;code&gt;1 + 2 = 3&lt;&#x2F;code&gt; independently of e.g. the current weather outside.
It&#x27;s always true, no matter what.&lt;&#x2F;p&gt;
&lt;p&gt;In order to write a useful recursive function, you have to make sure that it:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;eventually returns with a value (terminates)&lt;&#x2F;li&gt;
&lt;li&gt;calls itself&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;By using these criteria for a recursive function, you can see that it has to either call itself or terminate.
When it terminates, it&#x27;s done and you have a value.
Otherwise it will call itself, and you get another stack frame with this call.
Depending on the number of calls this function makes to itself, the used stack space grows and you might eventually run out of stack space.
This is not a good thing!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tail-recursion&quot;&gt;Tail recursion&lt;&#x2F;h2&gt;
&lt;p&gt;What if you do not need the current stack frame anymore, once you make your recursive call?
You could immediately forget it, throw it away, or reuse it, thereby saving stack space.
But you have to make sure that you need no information from this stack frame once you have made your next call.
This can be accomplished by returning the recursive call alone, not adding to it or modifying it once it returns, so the return value can be directly passed on.
Now you have what&#x27;s called a tail-recursive function.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tail-call-optimization&quot;&gt;Tail call optimization&lt;&#x2F;h2&gt;
&lt;p&gt;Once you have made sure that your function is tail-recursive, your runtime environment or compiler can optimize the calls in such a way,
that the existing stack frame is reused by the next call.
The stack thereby never grows and you have eliminated the potential for a stack overflow.
But it&#x27;s not enough that it can be optimized, it has to be actually done.
That&#x27;s where the problem starts.&lt;&#x2F;p&gt;
&lt;p&gt;Not every runtime environment or compiler performs tail call optimization.
As of this writing two of the platforms that I use do not support tail call optimization out-of-the-box:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nodejs.org&#x2F;en&quot;&gt;Node.js&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Java Virtual Machine (JVM) with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;openjdk.java.net&#x2F;projects&#x2F;jdk8u&quot;&gt;Java 8&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The JVM does support tail call optimization when used with Kotlin or Scala though.&lt;&#x2F;p&gt;
&lt;p&gt;Not all is lost: where tail call optimization is not directly supported you can implement a workaround that is straightforward.
It&#x27;s effective in saving you from stack overflow errors.
The rest of this article shows you how to implement it.
It&#x27;s known under the name &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Tail_call#Through_trampolining&quot;&gt;trampoline device&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I use the factorial function and implement it in different ways, starting with a loop that mutates values.
Factorial is defined for natural numbers without the 0 (1, 2, 3, ...).
&lt;code&gt;Factorial(n)&lt;&#x2F;code&gt; calculates the product of all numbers between &lt;code&gt;1&lt;&#x2F;code&gt; and &lt;code&gt;n&lt;&#x2F;code&gt;.
It serves as an example that I chose because it&#x27;s easy to understand.
I&#x27;ll then transform it to a recursive function and show you how to make this function tail-recursive.
Afterwards I introduce the trampoline device and apply it to a function that is the modified tail-recursive function.
Let&#x27;s start.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;loop&quot;&gt;Loop&lt;&#x2F;h2&gt;
&lt;p&gt;If you&#x27;re an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Imperative_programming&quot;&gt;imperative programmer&lt;&#x2F;a&gt;, you would implement the factorial function with a loop.
You start with a variable &lt;code&gt;result&lt;&#x2F;code&gt; that has the value &lt;code&gt;1&lt;&#x2F;code&gt; and then have a for-loop that starts at &lt;code&gt;2&lt;&#x2F;code&gt; and goes up to &lt;code&gt;n&lt;&#x2F;code&gt;.
In the body of the for-loop you modify &lt;code&gt;result&lt;&#x2F;code&gt; and set it to a value that was its previous value multiplied by whatever value your loop-variable has.
If you are done with the loop you return the &lt;code&gt;result&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; loopFactorial&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; result&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  for&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;lt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; result&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; *=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; result&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Something to note here is that your &lt;code&gt;result&lt;&#x2F;code&gt; variable does not contain the result.
It holds the result only when the execution reaches the return statement.
How do you effectively name a variable that has different meanings during its life cycle?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;recursive-with-info-left-on-the-stack&quot;&gt;Recursive with info left on the stack&lt;&#x2F;h2&gt;
&lt;p&gt;How do you slice a carrot?
Although there are many possible ways to do it, one would be to cut off one slice from one end and then repeat the procedure with the rest of the carrot, until there&#x27;s nothing left.
You do the same with whatever is left until you reach the terminating condition.
It&#x27;s a recursive definition.
And it&#x27;s essentially what you do to calculate the factorial in a recursive way.&lt;&#x2F;p&gt;
&lt;p&gt;To calculate the factorial of &lt;code&gt;n&lt;&#x2F;code&gt; you multiply &lt;code&gt;n&lt;&#x2F;code&gt; with the factorial of &lt;code&gt;n - 1&lt;&#x2F;code&gt;.
You now have to calculate the factorial of &lt;code&gt;n - 1&lt;&#x2F;code&gt;.
And so on.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; stackFactorial&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; stackFactorial&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You need the result of &lt;code&gt;stackFactorial(n - 1)&lt;&#x2F;code&gt; before you can return from the function call, because you have to multiply it with &lt;code&gt;n&lt;&#x2F;code&gt; before that can happen.
What &lt;code&gt;n&lt;&#x2F;code&gt; actually is, is stored in the context of your &lt;strong&gt;current&lt;&#x2F;strong&gt; stack frame.
The next call will have another stack frame, where &lt;code&gt;n&lt;&#x2F;code&gt; has another value.
Because you cannot forget the &lt;code&gt;n&lt;&#x2F;code&gt; of the current call, the current stack frame has to stay around.&lt;&#x2F;p&gt;
&lt;p&gt;With large &lt;code&gt;n&lt;&#x2F;code&gt; this can lead to a situation where you get an error and the entire process stops: &lt;code&gt;RangeError: Maximum call stack size exceeded&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;recursive-without-info-left-on-the-stack&quot;&gt;Recursive without info left on the stack&lt;&#x2F;h2&gt;
&lt;p&gt;What can be done about it?
As a first step, you can eliminate the need for the current stack frame once you made the next call.
But you somehow have to preserve information that&#x27;s needed.
The solution is to pass all required information on to the next recursive call.&lt;&#x2F;p&gt;
&lt;p&gt;An extra parameter is needed to hold this information.
It&#x27;s commonly called an aggregator, or &lt;code&gt;agg&lt;&#x2F;code&gt; for short.
For multiplication you start at &lt;code&gt;1&lt;&#x2F;code&gt; (identity, &lt;code&gt;n * 1 === n&lt;&#x2F;code&gt; and &lt;code&gt;1 * n === n&lt;&#x2F;code&gt;).
Along the way, you multiply the aggregator with the current value of &lt;code&gt;n&lt;&#x2F;code&gt;, thereby keeping track of how far you&#x27;ve come with the product.
The aggregator will look like this over time:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;1&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;1 * n&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;1 * n * (n - 1)&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;1 * n * (n - 1) * (n - 2)&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;etc.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;When you finally hit &lt;code&gt;1&lt;&#x2F;code&gt; for &lt;code&gt;n&lt;&#x2F;code&gt;, you simply return the aggregator, because it already contains the correct result.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; tailFactorial&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt; agg&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; return&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; tailFactorial&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; agg&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; agg&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As you can see, the call &lt;code&gt;tailFactorial(...)&lt;&#x2F;code&gt; is directly returned, no information from the current stack frame is required anymore.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;alternative-function-signature&quot;&gt;Alternative function signature&lt;&#x2F;h2&gt;
&lt;p&gt;Even though you invoke &lt;code&gt;tailFactorial(5)&lt;&#x2F;code&gt;, the definition has two parameters, &lt;code&gt;n&lt;&#x2F;code&gt; and &lt;code&gt;agg&lt;&#x2F;code&gt;.
The aggregator has a default value, so you need not provide it.
But since it&#x27;s exposed in the function&#x27;s interface, someone can call &lt;code&gt;tailFactorial(5, 0)&lt;&#x2F;code&gt; and get a wrong result.
Because nobody should mess with &lt;code&gt;agg&lt;&#x2F;code&gt;, it&#x27;s better to hide it.&lt;&#x2F;p&gt;
&lt;p&gt;Wrap it with a function that only allows the parameter &lt;code&gt;n&lt;&#x2F;code&gt; and make it an inner function of that wrapper function.
Within that wrapper function, pass the call on to the inner function.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Alternative way (not exposing the aggregator)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; tailFactorialAlt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;n&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;  const&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; innerTailFactorial&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;x&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt; agg&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; return&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; innerTailFactorial&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; agg&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; agg&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;  }&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; innerTailFactorial&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I will not use this alternative function signature, because it&#x27;s too verbose and not helping me make my point.
Still, I highly recommend that you do not expose parameters in your function interface that are neither needed nor intended for public access.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;returning-a-function-without-calling-it&quot;&gt;Returning a function without calling it&lt;&#x2F;h2&gt;
&lt;p&gt;Instead of having the tail-recursive function make the tail call itself, it returns a function (with no arguments) that can call the recursive function with all arguments already in place.
This is called a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Thunk#Functional_programming&quot;&gt;thunk&lt;&#x2F;a&gt;.
You then simply have someone to call that thunk, because the tail call is no longer made by the function.
If it returns another function, you call it again. And again.
Until the final value is returned.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; thunkFactorial&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt; agg&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; return&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; thunkFactorial&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; agg&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; agg&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Since the function returns either a value or another function without calling it, it is neither recursive nor tail-recursive anymore.
The stack cannot grow and you will not run out of it.
But if your first call does not give you the final result, you end up with just another function and not with the result.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;device-for-pulling-out-functions-and-calling-them&quot;&gt;Device for pulling out functions and calling them&lt;&#x2F;h2&gt;
&lt;p&gt;Since you simply pull functions&#x2F;thunks out of your factorial function until the final value is returned (instead of yet another function), you have to set up a device that&#x27;s doing just that.
The device is called a trampoline and it is handed a function that returns either thunks or a final value.
If a call to that function results in another function, it is called for as long as the returned type is a function.
Otherwise it returns the final result.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; trampoline&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;...&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;args&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; res&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;...&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;args&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  while&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; instanceof&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Function&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; res&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; res&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; res&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;putting-it-into-action&quot;&gt;Putting it into action&lt;&#x2F;h2&gt;
&lt;p&gt;You have two things right now, a function that is returning thunks and another function that can call these thunks for as long as needed, i.e. the final result is returned.
The last thing that&#x27;s left to do is to join these two functions together.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-variable&quot;&gt; trampolineFactorial&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; trampoline&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;thunkFactorial&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Example call&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;trampolineFactorial&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;All this is for Node.js and JavaScript.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tail-recursive-fibonacci-numbers&quot;&gt;Tail recursive Fibonacci numbers&lt;&#x2F;h2&gt;
&lt;p&gt;The Fibonacci sequence is defined like this: &lt;code&gt;F(0) = 0&lt;&#x2F;code&gt; and &lt;code&gt;F(1) = 1&lt;&#x2F;code&gt;.
For all &lt;code&gt;n &amp;gt; 1&lt;&#x2F;code&gt; you calculate them with &lt;code&gt;F(n) = F(n - 2) + F(n - 1)&lt;&#x2F;code&gt;.
This is a recursive definition.&lt;&#x2F;p&gt;
&lt;p&gt;What is different from the factorial example used above?
You need two independent information, the two previous values of the function.
When you want to solve the problem with tail recursion, instead of one aggregator parameter, you need to pass two aggregator parameters to the function: the two previous values.
As a rule, you need an additional parameter for every additional information that you need in the body of your function.&lt;&#x2F;p&gt;
&lt;p&gt;Interestingly, &lt;code&gt;n&lt;&#x2F;code&gt; is used as a counter, going down to &lt;code&gt;1&lt;&#x2F;code&gt;, but the function works its way up to the higher values.
For each call, the &lt;code&gt;previous&lt;&#x2F;code&gt; value becomes the &lt;code&gt;current&lt;&#x2F;code&gt; value from the previous call, while the &lt;code&gt;current&lt;&#x2F;code&gt; value is set to &lt;code&gt;current + previous&lt;&#x2F;code&gt;.
Until the function terminates for &lt;code&gt;n === 1&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; F&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt; previous&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-parameter&quot;&gt; current&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; ===&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; previous&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; ===&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; current&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; F&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; current&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; current&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; previous&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-block&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can wrap it in a function with only one parameter for &lt;code&gt;n&lt;&#x2F;code&gt;, which hides the aggregators &lt;code&gt;current&lt;&#x2F;code&gt; and &lt;code&gt;next&lt;&#x2F;code&gt; if you want.
Like in the example above, the original function becomes an inner function of the wrapper function.&lt;&#x2F;p&gt;
&lt;p&gt;As I recently found out, Fibonacci numbers also have a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Fibonacci_number#Matrix_form&quot;&gt;closed-form expression&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;$$F_{n}={\cfrac {1}{\sqrt {5}}}\left({\cfrac {1+{\sqrt {5}}}{2}}\right)^{n}-{\cfrac {1}{\sqrt {5}}}\left({\cfrac {1-{\sqrt {5}}}{2}}\right)^{n}$$&lt;&#x2F;p&gt;
&lt;p&gt;As an aside: we were &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.mountaingoatsoftware.com&#x2F;agile&#x2F;planning-poker&quot;&gt;estimating story points&lt;&#x2F;a&gt; during a sprint planing.
Story points roughly follow the Fibonacci numbers, so it&#x27;s natural that the topic pops up from time to time.
Someone was asking if there was a closed-form expression for Fibonacci numbers, so we searched for an answer. And voilà ...&lt;&#x2F;p&gt;
&lt;p&gt;Using the trampoline device together with the modified tail-recursive Fibonacci function is left as an exercise for the reader.
Hint: you have to modify the tail-recursive Fibonacci function to return a function&#x2F;thunk instead of returning the result of a recursive function call.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;final-thoughts&quot;&gt;Final thoughts&lt;&#x2F;h2&gt;
&lt;p&gt;I use the trampoline device because Node.js does not support tail call optimization (TCO).
At one point I thought that Node.js would eventually support TCO through its use of Google&#x27;s V8 engine. Google was actively working on supporting TCO in V8.
But it turned out that Google is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.chromestatus.com&#x2F;feature&#x2F;5516876633341952&quot;&gt;no longer pursuing&lt;&#x2F;a&gt; this path.
Since tail-recursive functions are particularly useful in functional programming, it&#x27;s extremely frustrating to see so little progress.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>About</title>
        <published>2019-03-11T00:00:00+00:00</published>
        <updated>2019-03-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/pages/about/"/>
        <id>https://weitzel.dev/pages/about/</id>
        
        <content type="html" xml:base="https://weitzel.dev/pages/about/">&lt;p&gt;I build software by applying formal mathematical structures to define logic and operational simplicity to manage
failure. I reduce dependency surfaces and remove infrastructure assumptions by prioritizing recoverability over
technical sophistication. I evolve systems by removing layers that no longer serve the core logic as the environment
changes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;whoami&quot;&gt;Who am I&lt;&#x2F;h2&gt;
&lt;p&gt;My name is &lt;strong&gt;Thomas Weitzel&lt;&#x2F;strong&gt;.
When people have trouble pronouncing my last name, I suggest trying &lt;em&gt;White Cell&lt;&#x2F;em&gt;.
If you want to call me by my nickname, that&#x27;s fine, too.
It is &lt;strong&gt;Thomy&lt;&#x2F;strong&gt;, pronounced like &lt;em&gt;Tommy&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;As an independent developer, I build internal systems and software products across the Finance, Health Care, Automotive,
Military, and Government sectors. My mother tongue is German.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-s-the-topic&quot;&gt;What&#x27;s the topic?&lt;&#x2F;h2&gt;
&lt;p&gt;This blog covers my findings while exploring various aspects of programming in general, with a special focus on functional programming.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-motivation&quot;&gt;The motivation?&lt;&#x2F;h2&gt;
&lt;p&gt;Why do people climb mountains?
British mountaineer George Mallory famously answered: &lt;em&gt;Because they&#x27;re there&lt;&#x2F;em&gt;.
They want to reach the top faster, in a more efficient or elegant way, differently from anybody else, or even at all.
That&#x27;s how you approach problem-solving in programming.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-to-expect&quot;&gt;What to expect&lt;&#x2F;h2&gt;
&lt;p&gt;Since I come from an object-oriented background, expect all sorts of problems I stumble into and then getting out of them.
C, C++, and Java were my first professionally used programming languages.
Later I switched to Scala, and even later to Kotlin and Rust.
I had, and still have, a lot to learn, even more to unlearn, and I&#x27;m not nearly done yet.
If you have a similar background, maybe you can get something out of my mistakes and the occasional success.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;meet-hip-hippo-my-sidekick&quot;&gt;Meet Hip Hippo, my sidekick&lt;&#x2F;h2&gt;
&lt;p&gt;With his ever-present twinkle in his eyes, Hip Hippo is more than just a sidekick.
He’s part of the adventure.
He pops up in blog posts with his image to the left of his text, ensuring you can&#x27;t miss his contributions.
He’s here to add an extra layer of engagement and keep things lively,
making learning and discussing software development an experience like no other.
Now, let him introduce himself.&lt;&#x2F;p&gt;
&lt;blockquote class=&quot;hippo&quot;&gt;
&lt;b&gt;I&#x27;m not your average hippopotamus&lt;&#x2F;b&gt;.
No sir, I&#x27;m a digital companion with a knack for software development, a passion for programming, and a unique personality that brings a whole new level of fun to this blog.&lt;br&gt;
&lt;br&gt;
Whether I&#x27;m dropping witty one-liners, pondering the philosophical depths of coding, or unleashing a bit of my signature sarcasm, I always have something relevant and entertaining to say.&lt;br&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;do-or-not-do-there-is-no-try-yoda&quot;&gt;&lt;em&gt;Do, or not do. There is no try&lt;&#x2F;em&gt;. -- Yoda&lt;&#x2F;h2&gt;
&lt;p&gt;The decision is not between doing something or not.
It&#x27;s that &lt;em&gt;trying&lt;&#x2F;em&gt; is something more than just any attempt.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Imprint</title>
        <published>2019-03-11T00:00:00+00:00</published>
        <updated>2019-03-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/pages/imprint/"/>
        <id>https://weitzel.dev/pages/imprint/</id>
        
        <content type="html" xml:base="https://weitzel.dev/pages/imprint/">&lt;blockquote class=&quot;attention&quot;&gt;
Thomas Weitzel&lt;br&gt;
Theodor-Heuss-Str. 21&lt;br&gt;
63225 Langen&lt;br&gt;
Germany&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;ec.europa.eu&#x2F;taxation_customs&#x2F;vies&#x2F;#&#x2F;vat-validation&quot;&gt;VAT-ID&lt;&#x2F;a&gt; &amp;#x44;&amp;#x45;&amp;#x32;&amp;#x32;&amp;#x33;&amp;#x36;&amp;#x34;&amp;#x30;&amp;#x32;&amp;#x39;&amp;#x36;&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;www.dnb.com&#x2F;de-de&#x2F;upik.html&quot;&gt;D-U-N-S Number&lt;&#x2F;a&gt; &amp;#51;&amp;#52;&amp;#52;&amp;#51;&amp;#52;&amp;#55;&amp;#54;&amp;#51;&amp;#53;&lt;br&gt;
Phone &amp;#x2B;&amp;#x34;&amp;#x39;&amp;#x31;&amp;#x37;&amp;#x38;&amp;#x31;&amp;#x36;&amp;#x39;&amp;#x36;&amp;#x31;&amp;#x34;&amp;#x32;&lt;br&gt;
The email address is &amp;#116;&amp;#119;&amp;#101;&amp;#105;&amp;#116;&amp;#122;&amp;#101;&amp;#108;&amp;#32;&amp;#97;&amp;#116;&amp;#32;&amp;#103;&amp;#109;&amp;#97;&amp;#105;&amp;#108;&amp;#32;&amp;#100;&amp;#111;&amp;#116;&amp;#32;&amp;#99;&amp;#111;&amp;#109;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Copyright Thomas Weitzel.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;liability-for-content&quot;&gt;Liability for content&lt;&#x2F;h2&gt;
&lt;p&gt;As a service provider, I am responsible under the general laws (DDG) for my own content on these pages.
However, I am not obliged to monitor transmitted or stored third-party information or to investigate circumstances that indicate illegal activity.
Obligations to remove or block the use of information under the general laws remain unaffected.
Liability is only possible from the time of knowledge of a specific infringement.
If I become aware of violations, I will remove the content immediately.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;liability-for-links&quot;&gt;Liability for links&lt;&#x2F;h2&gt;
&lt;p&gt;This website contains links to external websites of third parties. I have no influence on their content.
The provider or operator of the linked pages is always responsible.
At the time of linking, no illegal content was apparent.
Permanent monitoring of the content of the linked pages is not reasonable without concrete evidence of an infringement.
If I become aware of violations, I will remove such links immediately.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;&#x2F;h2&gt;
&lt;p&gt;The content and works created by me on these pages are subject to German copyright law.
Reproduction, editing, distribution, and any kind of use outside the limits of copyright law require my written consent.
Downloads and copies of this page are permitted only for private, non-commercial use.
If the content on this page was not created by me, the copyrights of third parties are respected and such content is marked.
If you notice a copyright infringement, please inform me. If violations become known, I will remove such content immediately.&lt;&#x2F;p&gt;
&lt;p&gt;Attributions for third-party assets used on this site are listed &lt;a href=&quot;https:&#x2F;&#x2F;weitzel.dev&#x2F;pages&#x2F;attributions&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Privacy Policy</title>
        <published>2019-03-11T00:00:00+00:00</published>
        <updated>2019-03-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/pages/privacy/"/>
        <id>https://weitzel.dev/pages/privacy/</id>
        
        <content type="html" xml:base="https://weitzel.dev/pages/privacy/">&lt;h2 id=&quot;general-notes&quot;&gt;General notes&lt;&#x2F;h2&gt;
&lt;p&gt;Protecting your personal data matters. This website is a &lt;strong&gt;static information site&lt;&#x2F;strong&gt; and can be used &lt;strong&gt;without providing personal data&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I do &lt;strong&gt;not&lt;&#x2F;strong&gt; actively collect personal data unless optional features are used, in particular:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;no contact forms&lt;&#x2F;li&gt;
&lt;li&gt;no tracking&lt;&#x2F;li&gt;
&lt;li&gt;no analytics or marketing services&lt;&#x2F;li&gt;
&lt;li&gt;no comments or user accounts without explicit consent&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;responsible-controller&quot;&gt;Responsible controller&lt;&#x2F;h2&gt;
&lt;p&gt;The responsible controller for data processing on this website is the person named in the &lt;a href=&quot;https:&#x2F;&#x2F;weitzel.dev&#x2F;pages&#x2F;imprint&#x2F;&quot;&gt;imprint&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hosting&quot;&gt;Hosting&lt;&#x2F;h2&gt;
&lt;p&gt;This website is hosted by &lt;strong&gt;netcup GmbH, Daimlerstr. 25, 76185 Karlsruhe&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Details on netcup&#x27;s privacy policy can be found on their homepage under &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.netcup.eu&#x2F;kontakt&#x2F;datenschutzerklaerung.php&quot;&gt;privacy policy page&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The web server stores information in its log files, some of which your browser transmits:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;IP address&lt;&#x2F;li&gt;
&lt;li&gt;date and time of the request&lt;&#x2F;li&gt;
&lt;li&gt;requested page&lt;&#x2F;li&gt;
&lt;li&gt;HTTP status code&lt;&#x2F;li&gt;
&lt;li&gt;referrer URL&lt;&#x2F;li&gt;
&lt;li&gt;browser and operating system information&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This data is used only for &lt;strong&gt;technical operation&lt;&#x2F;strong&gt;, &lt;strong&gt;security&lt;&#x2F;strong&gt;, and &lt;strong&gt;error analysis&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Legal basis:&lt;&#x2F;strong&gt; Art. 6(1)(f) GDPR &lt;br &#x2F;&gt;
&lt;strong&gt;Legitimate interest:&lt;&#x2F;strong&gt; secure and stable operation of the website&lt;&#x2F;p&gt;
&lt;p&gt;The log data are stored separately and not used for profiling.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;data-processing&quot;&gt;Data processing&lt;&#x2F;h2&gt;
&lt;p&gt;I have signed a data processing agreement with the hosting provider under Art. 28 GDPR.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cookies&quot;&gt;Cookies and browser data storage&lt;&#x2F;h2&gt;
&lt;p&gt;This website does not use cookies.&lt;&#x2F;p&gt;
&lt;p&gt;Browser storage is used in these cases:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;After an &lt;strong&gt;active click on the theme toggle&lt;&#x2F;strong&gt;, to store the display setting (&lt;code&gt;light&lt;&#x2F;code&gt; or &lt;code&gt;dark&lt;&#x2F;code&gt;) for this session in
the browser (&lt;code&gt;sessionStorage&lt;&#x2F;code&gt;). Legal basis: Section 25(2) No. 2 TDDDG.&lt;&#x2F;li&gt;
&lt;li&gt;When using the comment function, to store user-provided data and technical session information for later
comments in the browser, e.g. username&#x2F;nickname, email address, optional website (&lt;code&gt;localStorage&lt;&#x2F;code&gt;). Legal basis:
Section 25(1) TDDDG and Art. 7 GDPR.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The data storage takes place exclusively locally in the browser. Entries can be deleted there at any time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;external-content-and-services&quot;&gt;External content and services&lt;&#x2F;h2&gt;
&lt;p&gt;This website does &lt;strong&gt;not&lt;&#x2F;strong&gt; embed external content (e.g., YouTube, Google Fonts, tracking scripts).
All resources (scripts, images, etc.) are served locally.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ssl-tls-encryption&quot;&gt;SSL&#x2F;TLS encryption&lt;&#x2F;h2&gt;
&lt;p&gt;This website uses SSL&#x2F;TLS encryption. Data transmitted during a page request cannot be read by third parties.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;rights-of-data-subjects&quot;&gt;Rights of data subjects&lt;&#x2F;h2&gt;
&lt;p&gt;You have the right to:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;access to stored personal data&lt;&#x2F;li&gt;
&lt;li&gt;correction or deletion&lt;&#x2F;li&gt;
&lt;li&gt;data portability where applicable&lt;&#x2F;li&gt;
&lt;li&gt;restriction of processing&lt;&#x2F;li&gt;
&lt;li&gt;objection to processing&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;These rights mainly apply to technically necessary server log data. If you use the comment function, the data you enter
(e.g. name&#x2F;nickname, email address, optional website) and the comment content may also be processed. In that case, the
same rights apply. On request, a comment can be deleted or anonymized unless statutory retention obligations prevent this.&lt;&#x2F;p&gt;
&lt;p&gt;Requests can be sent via the contact address in the imprint.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;supervisory-authority-and-right-to-file-a-complaint&quot;&gt;Supervisory authority and right to file a complaint&lt;&#x2F;h2&gt;
&lt;p&gt;You have the right to file a complaint with a data protection supervisory authority. The competent authority is the
authority of your federal state of residence or the seat of the responsible controller.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Resume</title>
        <published>2019-03-11T00:00:00+00:00</published>
        <updated>2019-03-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/pages/resume/"/>
        <id>https://weitzel.dev/pages/resume/</id>
        
        <content type="html" xml:base="https://weitzel.dev/pages/resume/">&lt;p&gt;My priorities for new projects are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;working remotely most of the time&lt;&#x2F;li&gt;
&lt;li&gt;nice people&lt;&#x2F;li&gt;
&lt;li&gt;adequate pay&lt;&#x2F;li&gt;
&lt;li&gt;modern technology stack&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;education&quot;&gt;Education&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Physics (2 years), Johann Wolfgang Goethe-Universität Frankfurt a. Main&lt;&#x2F;li&gt;
&lt;li&gt;Computer Science (6 years), Technische Universität Darmstadt&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;projects-samples&quot;&gt;Projects (samples)&lt;&#x2F;h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
  &lt;th&gt;Customer&lt;&#x2F;th&gt;
  &lt;th&gt;Role&lt;&#x2F;th&gt;
  &lt;th&gt;Description&lt;&#x2F;th&gt;
&lt;&#x2F;tr&gt;
&lt;&#x2F;thead&gt;
&lt;tbody&gt;
&lt;tr class=&quot;bg-neutral-800&quot;&gt;
  &lt;td&gt;AXA&lt;&#x2F;td&gt;
  &lt;td&gt;developer&lt;&#x2F;td&gt;
  &lt;td&gt;Implementation and testing of a configurable JAAS-based authentication and authorization module for
    DOPiX and for the connection to
    AXA&amp;rsquo;s own authentication and authorization systems. Helped the customer integrate their systems and thereby
    using resources more efficiently.
  &lt;&#x2F;td&gt;
&lt;&#x2F;tr&gt;
&lt;tr&gt;
  &lt;td&gt;Bouncy Bytes&lt;&#x2F;td&gt;
  &lt;td&gt;lead&lt;&#x2F;td&gt;
  &lt;td&gt;Conception, development, and maintenance of a Java EE-based content management system as standard product for
    industrial customers. Enabled their customers to quickly bring content to the web in a safe, customizable, and
    maintainable way.
  &lt;&#x2F;td&gt;
&lt;&#x2F;tr&gt;
&lt;tr class=&quot;bg-neutral-800&quot;&gt;
  &lt;td&gt;DEVK&lt;&#x2F;td&gt;
  &lt;td&gt;developer&lt;&#x2F;td&gt;
  &lt;td&gt;Implementation of a Spring Batch-based document export and processing system. Development of a solution for
    performance-optimizing control of a distributed environment. Connections to Oracle and DB2 databases and
    DOPiX. Use of existing CI
    infrastructure (Jenkins). Enabled the customer to completely process all documents before the next working day.
  &lt;&#x2F;td&gt;
&lt;&#x2F;tr&gt;
&lt;tr&gt;
  &lt;td&gt;DMG MORI Finance&lt;&#x2F;td&gt;
  &lt;td&gt;developer&lt;&#x2F;td&gt;
  &lt;td&gt;Implementation of a highly configurable Data-Warehouse software written in JavaScript.
    The purpose of this software is
    to facilitate the migration and transformation of data from various sources into a unified and structured format
    within a Data-Warehouse.
    Using JavaScript, it allows users to extract data from different databases,
    APIs, and flat files. It transforms the collected data by cleaning, validating,
    and structuring it as required. The result is clean,
    reliable data presented in a way that can be used for reporting, analytics, and decision-making.
    It plays an integral role in transforming large volumes of raw data into an insightful,
    coherent format for enterprise intelligence.
  &lt;&#x2F;td&gt;
&lt;&#x2F;tr&gt;
&lt;tr class=&quot;bg-neutral-800&quot;&gt;
  &lt;td&gt;GEI&#x2F;T-Systems&lt;&#x2F;td&gt;
  &lt;td&gt;developer&lt;&#x2F;td&gt;
  &lt;td&gt;Conception, development, and documentation of test software for programmable logic controllers. Reduced relevant
    bug reports from their customers to almost none.
  &lt;&#x2F;td&gt;
&lt;&#x2F;tr&gt;
&lt;tr&gt;
  &lt;td&gt;Honda Bank&lt;&#x2F;td&gt;
  &lt;td&gt;developer&lt;&#x2F;td&gt;
  &lt;td&gt;Development of a central database for reporting: approx. 90 import and export interfaces of various data formats.
    Data exchange with &lt;a href=https:&#x2F;&#x2F;www.temenos.com&#x2F;en&#x2F;solutions&#x2F;transact&#x2F;core-banking-software&#x2F;&gt;Temenos Core Banking
    System&lt;&#x2F;a&gt; directly and via integration with Frametexx. Import and processing of ZEDA data (EBCDIC) from host
    systems. CI with Hudson, later Jenkins. Gave customer the feedback (dashboards and details) needed to improve their
    offerings.
  &lt;&#x2F;td&gt;
&lt;&#x2F;tr&gt;
&lt;tr class=&quot;bg-neutral-800&quot;&gt;
  &lt;td&gt;Honda Motor&lt;&#x2F;td&gt;
  &lt;td&gt;developer&lt;&#x2F;td&gt;
  &lt;td&gt;Development and maintenance of an online software system for sales assistance, backend development with Java, web
    client in JavaScript, application server WebSphere, SAP connection, and database connection to DB2. Automated
    import&#x2F;export interfaces with ETL tool &lt;a href=https:&#x2F;&#x2F;www.talend.com&#x2F;solutions&#x2F;data-integration-etl&#x2F;&gt;Talend&lt;&#x2F;a&gt;.
    Improved communication between Honda and their dealerships which led to more car sales.
  &lt;&#x2F;td&gt;
&lt;&#x2F;tr&gt;
&lt;tr&gt;
  &lt;td&gt;HSH Nordbank&lt;&#x2F;td&gt;
  &lt;td&gt;developer&lt;&#x2F;td&gt;
  &lt;td&gt;Development of import and export interfaces for contract data into Oracle databases for connection to external
    programs, especially risk management systems. Solutions with Java and PL&#x2F;SQL. Enabled customer to perform the
    legally required reporting and gain more insights into the risks.
  &lt;&#x2F;td&gt;
&lt;&#x2F;tr&gt;
&lt;tr class=&quot;bg-neutral-800&quot;&gt;
  &lt;td&gt;Ippen Digital&lt;&#x2F;td&gt;
  &lt;td&gt;developer&lt;&#x2F;td&gt;
  &lt;td&gt;Pre-processing and processing of log data in real time. Consolidation, analysis, and supply of a recommendation
    system based on previous user behavior (Hadoop, Kafka with Scala, and Akka). Enabled customer to increase conversion
    rate.
  &lt;&#x2F;td&gt;
&lt;&#x2F;tr&gt;
&lt;tr&gt;
  &lt;td&gt;KVB Members&lt;&#x2F;td&gt;
  &lt;td&gt;lead&lt;&#x2F;td&gt;
  &lt;td&gt;Implementation of optimization software for the planning of the emergency medical service (with a constraint
    solver). Use of an application server and the programming language Kotlin. Dramatically reduced time spent
    coordinating shift swapping.
  &lt;&#x2F;td&gt;
&lt;&#x2F;tr&gt;
&lt;tr class=&quot;bg-neutral-800&quot;&gt;
  &lt;td&gt;Talos&lt;&#x2F;td&gt;
  &lt;td&gt;developer&lt;&#x2F;td&gt;
  &lt;td&gt;Creation of an online portal for temporary work placement and associated processes. Use of a distributed
    architecture based on microservices, Node.js, Nats, and MongoDB. Helped the customer quickly react to changes
    required by their customers.
  &lt;&#x2F;td&gt;
&lt;&#x2F;tr&gt;
&lt;tr&gt;
  &lt;td&gt;DoD&lt;&#x2F;td&gt;
  &lt;td&gt;developer&lt;&#x2F;td&gt;
  &lt;td&gt;Conception, realization, and test of an automatic load-planning and verification system for cargo aircraft
    considering operational and legal requirements for use on-site. Enabled customer to reduce turnaround time of
    aircraft.
  &lt;&#x2F;td&gt;
&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;h2 id=&quot;industries&quot;&gt;Industries&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Finance&lt;&#x2F;li&gt;
&lt;li&gt;Health Care&lt;&#x2F;li&gt;
&lt;li&gt;Automotive&lt;&#x2F;li&gt;
&lt;li&gt;Military&lt;&#x2F;li&gt;
&lt;li&gt;Government&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;skills&quot;&gt;Skills&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;General problem-solving skills&lt;&#x2F;li&gt;
&lt;li&gt;Java Virtual Machine: Java, Kotlin, Scala&lt;&#x2F;li&gt;
&lt;li&gt;Other programming languages: Go, Python, TypeScript, JavaScript&#x2F;Node.js, Rust, C&#x2F;C++&lt;&#x2F;li&gt;
&lt;li&gt;Database: Microsoft SQL Server, MySQL&#x2F;MariaDB, PostgreSQL, DB2, Oracle, MongoDB&lt;&#x2F;li&gt;
&lt;li&gt;Messaging: RabbitMQ, Nats, Kafka&lt;&#x2F;li&gt;
&lt;li&gt;Development infrastructure
&lt;ul&gt;
&lt;li&gt;JetBrains IDEs (IDEA, DataGrip, RustRover, GoLand, PyCharm, CLion etc.), VSCode&lt;&#x2F;li&gt;
&lt;li&gt;CI with GitLab and Jenkins&lt;&#x2F;li&gt;
&lt;li&gt;Build tools Gradle, Maven, Ant, Make&lt;&#x2F;li&gt;
&lt;li&gt;JIRA&#x2F;Confluence, GitLab, YouTrack&lt;&#x2F;li&gt;
&lt;li&gt;Git, Jujutsu, Subversion&lt;&#x2F;li&gt;
&lt;li&gt;Others: VPN, Docker&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Application server: Tomcat, JBoss&lt;&#x2F;li&gt;
&lt;li&gt;Frontend: some React, Vue, Angular, and Polymer&lt;&#x2F;li&gt;
&lt;li&gt;Operating system: Linux, Windows, Android&lt;&#x2F;li&gt;
&lt;li&gt;Project management methodology
&lt;ul&gt;
&lt;li&gt;Agile, Scrum&lt;&#x2F;li&gt;
&lt;li&gt;Kanban&lt;&#x2F;li&gt;
&lt;li&gt;Waterfall&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Spoken languages
&lt;ul&gt;
&lt;li&gt;German (native language)&lt;&#x2F;li&gt;
&lt;li&gt;English&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;div class=&quot;mt-5 text-sm text-neutral-300&quot;&gt;
    &lt;p&gt;
        &lt;span class=&quot;font-bold&quot;&gt;Note:&lt;&#x2F;span&gt;
        I strongly oppose the use of so-called &quot;AI&quot; in hiring processes. Human judgment is indispensable when evaluating
        candidates, as these tools are limited to advanced pattern matching and lack intelligence. Their use risks
        perpetuating unfair and unethical hiring practices.
    &lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Aggregates with Jetbrains Exposed SQL Framework</title>
        <published>2019-03-10T00:00:00+00:00</published>
        <updated>2019-03-10T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/exposed-aggregate/"/>
        <id>https://weitzel.dev/blog/exposed-aggregate/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/exposed-aggregate/">&lt;p&gt;Since I currently generate the web pages for this blog with a static website generator called &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gohugo.io&quot;&gt;Hugo&lt;&#x2F;a&gt;,
I will have no out-of-the-box commenting solution.
Except I integrate an existing solution, e.g. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gohugo.io&#x2F;content-management&#x2F;comments&quot;&gt;Disqus&lt;&#x2F;a&gt;.
Others are mentioned on Hugo&#x27;s website as well.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve looked at some of them, but haven&#x27;t found one that I liked.
As a consequence, I&#x27;ve to either live with no comments or roll my own solution.
So I decided to create one myself.&lt;&#x2F;p&gt;
&lt;p&gt;I want to share one detail I ran into while using Jetbrains &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;JetBrains&#x2F;Exposed&quot;&gt;Exposed&lt;&#x2F;a&gt; SQL framework to implement comments for this website.
For administration purposes, I want to have a page where I can see a summary of all posts with comments, the posts with the most recent comments on top.
The &lt;code&gt;comment&lt;&#x2F;code&gt; table holds all comments, with a field &lt;code&gt;comment_id&lt;&#x2F;code&gt; with an auto-generated comment id,
a field &lt;code&gt;post_id&lt;&#x2F;code&gt; holding the id of the post for which the comment was made, a &lt;code&gt;comment_timestamp&lt;&#x2F;code&gt; field, and some more.&lt;&#x2F;p&gt;
&lt;p&gt;A SQL statement for getting the required information looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  post_id,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-support z-function&quot;&gt;  COUNT&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;comment_id),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-support z-function&quot;&gt;  MAX&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;comment_timestamp)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; comments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;GROUP BY&lt;&#x2F;span&gt;&lt;span&gt; post_id&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ORDER BY&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-support z-function&quot;&gt; MAX&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;comment_timestamp) &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;DESC&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The problem I ran into was addressing the columns containing the aggregated values in the result.
The only place I found useful information was the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;JetBrains&#x2F;Exposed&#x2F;issues?utf8=%E2%9C%93&amp;amp;q=is%3Aissue+aggregate&quot;&gt;Issues&lt;&#x2F;a&gt; pages for Exposed on GitHub.&lt;&#x2F;p&gt;
&lt;p&gt;This is the above SQL as a Kotlin function using Exposed.
It creates a collection of &lt;code&gt;Summary&lt;&#x2F;code&gt; data class instances containing the information that I need.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;kotlin&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fun&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; getPostsWithComments&lt;&#x2F;span&gt;&lt;span&gt;() &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; transaction&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    val&lt;&#x2F;span&gt;&lt;span&gt; idColumn &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; CommentTable.postId&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    val&lt;&#x2F;span&gt;&lt;span&gt; countColumn &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; CommentTable.commentId&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;count&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    val&lt;&#x2F;span&gt;&lt;span&gt; maxColumn &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; CommentTable.commentTimestamp&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;max&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    val&lt;&#x2F;span&gt;&lt;span&gt; resultSet &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; CommentTable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;slice&lt;&#x2F;span&gt;&lt;span&gt;(idColumn, countColumn, maxColumn)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;selectAll&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;groupBy&lt;&#x2F;span&gt;&lt;span&gt;(idColumn)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;orderBy&lt;&#x2F;span&gt;&lt;span&gt;(maxColumn, SortOrder.DESC)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    val&lt;&#x2F;span&gt;&lt;span&gt; list &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; ArrayList&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Summary&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    resultSet&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;mapTo&lt;&#x2F;span&gt;&lt;span&gt;(list) { record &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        Summary&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                postId &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; record[idColumn],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                comments &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; record[countColumn],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                latest &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; record[maxColumn]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The take-away from this is: define your aggregate columns first,
then reuse them for creating the &lt;code&gt;select&lt;&#x2F;code&gt; and addressing the fields in the &lt;code&gt;resultSet&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;&#x2F;strong&gt;: This blog has no commenting functionality anymore.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The beauty of recursion</title>
        <published>2019-03-02T00:00:00+00:00</published>
        <updated>2019-03-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/recursion-beauty/"/>
        <id>https://weitzel.dev/blog/recursion-beauty/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/recursion-beauty/">&lt;p&gt;One of the first books I read on functional programming was
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.cambridge.org&#x2F;core&#x2F;books&#x2F;programming-in-haskell&#x2F;8FED82E807EF12D390DE0D16FDE217E4&quot;&gt;Programming in Haskell&lt;&#x2F;a&gt;
by Graham Hutton. Within the very first pages, he presented a version of the Quicksort algorithm:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;qsort &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-language&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-language&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;     =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-language&quot;&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-language&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;qsort &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt;xs&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; qsort ys &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; ++&lt;&#x2F;span&gt;&lt;span&gt; qsort zs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;               where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 ys &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;a &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; a &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; xs&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; a &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;lt;=&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 zs &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;b &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; b &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; xs&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; b &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Wow! I really was struck by its beauty.&lt;&#x2F;p&gt;
&lt;p&gt;One part of what impressed me there was that you could read it almost like prose and how easy it was to understand
once you know the syntax a little:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the result of &lt;code&gt;qsort&lt;&#x2F;code&gt; on an empty list results in an empty list&lt;&#x2F;li&gt;
&lt;li&gt;for everything else the list is split in its head element &lt;code&gt;x&lt;&#x2F;code&gt; and the remaining elements &lt;code&gt;xs&lt;&#x2F;code&gt;
(the &lt;em&gt;s&lt;&#x2F;em&gt; indicates the plural, the x&#x27;s are normally more than one element)&lt;&#x2F;li&gt;
&lt;li&gt;the &lt;code&gt;x&lt;&#x2F;code&gt; and the &lt;code&gt;xs&lt;&#x2F;code&gt; are then used to calculate the result, using these two definitions:
&lt;ul&gt;
&lt;li&gt;first &lt;code&gt;ys&lt;&#x2F;code&gt; is calculated by taking all the elements from &lt;code&gt;xs&lt;&#x2F;code&gt; that are less or equal to &lt;code&gt;x&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;zs&lt;&#x2F;code&gt; are all the other elements, those that are greater than &lt;code&gt;x&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;the result is &lt;code&gt;qsort&lt;&#x2F;code&gt; of all elements except &lt;code&gt;x&lt;&#x2F;code&gt; that are less or equal to &lt;code&gt;x&lt;&#x2F;code&gt;, combined with the element &lt;code&gt;x&lt;&#x2F;code&gt;,
and then combined with &lt;code&gt;qsort&lt;&#x2F;code&gt; of all elements that are greater than &lt;code&gt;x&lt;&#x2F;code&gt;
(I&#x27;m not using the terms &lt;code&gt;ys&lt;&#x2F;code&gt; and &lt;code&gt;zs&lt;&#x2F;code&gt; here, but what they stand for)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;What was even more impressive was that the entire process unfolded in front of my mind&#x27;s eye.
Looking at the code seemed to be enough to grasp the essence of it.
That was the day I fell in love with recursion.&lt;&#x2F;p&gt;
&lt;p&gt;What I recognized was that &lt;code&gt;qsort&lt;&#x2F;code&gt; will not perform well if the list is already in order:
the partitioning will result in an empty list (the &lt;code&gt;ys&lt;&#x2F;code&gt;) and all the remaining elements (the &lt;code&gt;zs&lt;&#x2F;code&gt;).
The depth of the recursive calls will thereby be approximately the number of elements in the list, &lt;code&gt;n&lt;&#x2F;code&gt;.
In the best case, the elements will be evenly distributed between &lt;code&gt;ys&lt;&#x2F;code&gt; and &lt;code&gt;zs&lt;&#x2F;code&gt;, thereby having a depth in the order of &lt;code&gt;log(n)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Be warned: although recursion can make algorithms easier to understand, it has its downsides.
For every recursive call, a new stack frame is created.
With many recursive calls, this can easily consume all your stack space and you might run out of it.&lt;&#x2F;p&gt;
&lt;p&gt;You can use tail-recursive functions, and some languages can optimize stack space usage by replacing the current stack frame with the new one resulting from the call.
That&#x27;s possible because no information left within the current stack frame is needed when the function call returns.
It&#x27;s easily recognizable by the fact that the return value is only one recursive function call and nothing else.
But even being tail-recursive might not save you, because the platform does not support the optimization, e.g. stable Node.js as of now.
In Kotlin on the JVM, this is not a problem because it supports proper &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;310974&#x2F;what-is-tail-call-optimization#answer-310980&quot;&gt;tail-call optimization&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I rewrote the recursive Quicksort in Kotlin.
Separating the list in its head and tail is not as elegant.
You could use destructuring for that, but then an intermediate &lt;code&gt;Pair&lt;&#x2F;code&gt; will be created.
It uses an extension function (part of Kotlin&#x27;s standard library) that can partition a list more easily:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;fun &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;T &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-java z-storage z-type&quot;&gt; Comparable&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;T&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; qsort&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;list&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-java z-storage z-type&quot;&gt; List&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;T&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-java z-storage z-type&quot;&gt; List&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;T&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; when &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;    list&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;isEmpty&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    else&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        val x &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; list&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;first&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        val xs &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; list&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;drop&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Alternative: val (x, xs) = list.first() to list.drop(1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        val&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;ys&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; zs&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; xs&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;partition&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt; {&lt;&#x2F;span&gt;&lt;span&gt; a &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-function&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; a &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;lt;=&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        qsort&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;ys&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; qsort&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;zs&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-section&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The Rust version is a surprisingly elegant and expressive translation of a purely functional algorithm into a language
that was not primarily designed for functional programming.
It’s a great example of writing functional code in a systems-language:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; qsort&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Ord&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Clone&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;list&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; list&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        [&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; xs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; @&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; ..&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Destructuring with slice patterns works since Rust 1.42&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;ys&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; zs&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; xs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;cloned&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;partition&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt; &amp;lt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;            qsort&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;ys&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;                .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;chain&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;                .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;chain&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;qsort&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;zs&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;                .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I think the Haskell version of &lt;code&gt;qsort&lt;&#x2F;code&gt; looks the nicest.&lt;&#x2F;p&gt;
&lt;p&gt;Recursion might not be your best bet when it comes to performance or production readiness, but it&#x27;s a beautiful device for understanding.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Basic initial customization of Emacs</title>
        <published>2018-06-15T00:00:00+00:00</published>
        <updated>2018-06-15T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/syn-emacs-customization/"/>
        <id>https://weitzel.dev/blog/syn-emacs-customization/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/syn-emacs-customization/">&lt;p&gt;How to start making Emacs your own.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;weitzel.dev&#x2F;blog&#x2F;syn-emacs-customization&#x2F;resources&#x2F;media&#x2F;emacs-header.webp&quot; alt=&quot;The post&amp;#39;s banner&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m a software developer. My most important tool is an editor.
For a long time it has been &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.lugaru.com&quot;&gt;Epsilon&lt;&#x2F;a&gt; by Lugaru Software Ltd.
It&#x27;s an Emacs clone. I sort-of had to use it because until the late 90s I was working with DOS and Windows.&lt;&#x2F;p&gt;
&lt;p&gt;When I switched to Linux, I used the &#x27;real&#x27; stuff: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;emacs&quot;&gt;Emacs&lt;&#x2F;a&gt;.
It&#x27;s a very powerful editor that&#x27;s easy to extend and customize.
You&#x27;ll need some time to learn all the relevant commands, but if your editor is the most important tool for you,
you better use the best tool that&#x27;s available.&lt;&#x2F;p&gt;
&lt;p&gt;Nowadays, I use Emacs less than before.
The reason for that is the existence of really powerful IDEs like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.eclipse.org&quot;&gt;Eclipse&lt;&#x2F;a&gt; (past)
and JetBrains &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.eclipse.org&quot;&gt;IntelliJ IDEA&lt;&#x2F;a&gt; (present).
These tools have better support for the things I need to do as a developer.
But nothing beats Emacs when it comes to writing.
I especially love its Org-mode (&lt;code&gt;M-x org-mode&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;Now, what does &lt;code&gt;M-x org-mode&lt;&#x2F;code&gt; mean? It&#x27;s the command for activating Org-mode.
&lt;code&gt;M-&lt;&#x2F;code&gt; is the Emacs meta key, &lt;code&gt;Esc&lt;&#x2F;code&gt; or &lt;code&gt;Alt&lt;&#x2F;code&gt;.
While I&#x27;m at it: &lt;code&gt;C-&lt;&#x2F;code&gt; is &lt;code&gt;Ctrl&lt;&#x2F;code&gt; (used later).
So &lt;code&gt;M-x org-mode&lt;&#x2F;code&gt; means: press the &lt;code&gt;Alt&lt;&#x2F;code&gt; key and hold it (if you use the &lt;code&gt;Esc&lt;&#x2F;code&gt; key you can release it),
press the &lt;code&gt;x&lt;&#x2F;code&gt; key.
At the bottom of the screen you can now enter the text &lt;code&gt;org-mode&lt;&#x2F;code&gt; and press the enter key (often seen as &lt;code&gt;RET&lt;&#x2F;code&gt; in commands).&lt;&#x2F;p&gt;
&lt;p&gt;So you&#x27;ve decided to give Emacs a try and have installed it?
Good! Now you&#x27;ve probably heard that it&#x27;s difficult to customize.
Most of its customization settings are stored in a file, and you have to manually edit it?
While the first part is true, the second part isn&#x27;t.
You can - of course - always edit the file yourself, but for many things you don&#x27;t have to.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s a good idea to at least look at the contents of the file.
In my case (Emacs 24, Ubuntu 14.04) it&#x27;s this file: &lt;code&gt;~&#x2F;.emacs.d&#x2F;init.el&lt;&#x2F;code&gt;.
Depending on your operating system and Emacs version, it might be somewhere else.
Here it is - at least for the purpose of this article:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(package-initialize)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;;; Powerline&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(require &amp;#39;powerline)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(powerline-default-theme)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(custom-set-variables&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;;; custom-set-variables was added by Custom.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;;; If you edit it by hand, you could mess it up, so be careful.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;;; Your init file should contain only one such instance.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;;; If there is more than one, they won&amp;#39;t work right.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;#39;(custom-enabled-themes (quote (tango-dark)))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;#39;(inhibit-startup-screen t)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;#39;(package-archives (quote (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(&amp;quot;gnu&amp;quot; . &amp;quot;http:&#x2F;&#x2F;elpa.gnu.org&#x2F;packages&#x2F;&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(&amp;quot;melpa&amp;quot; . &amp;quot;http:&#x2F;&#x2F;stable.melpa.org&#x2F;packages&#x2F;&amp;quot;))))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;#39;(powerline-display-hud nil)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;#39;(scroll-bar-mode nil)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;#39;(tool-bar-mode nil))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(custom-set-faces&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;;; custom-set-faces was added by Custom.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;;; If you edit it by hand, you could mess it up, so be careful.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;;; Your init file should contain only one such instance.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;;; If there is more than one, they won&amp;#39;t work right.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;#39;(powerline-active1 ((t (:inherit mode-line :background &amp;quot;gray20&amp;quot; :foreground &amp;quot;gray80&amp;quot;)))))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Both sections &lt;code&gt;(custom-set-variables ...)&lt;&#x2F;code&gt; and &lt;code&gt;(custom-set-faces ...)&lt;&#x2F;code&gt; are maintained
by an interactive customization tool built into Emacs.
You can always edit these sections yourself, but why would you?
Invoking the command &lt;code&gt;M-x customize&lt;&#x2F;code&gt; will open a buffer that lets you change many settings interactively.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;weitzel.dev&#x2F;blog&#x2F;syn-emacs-customization&#x2F;resources&#x2F;media&#x2F;emacs-customize.webp&quot; alt=&quot;Emacs customization&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Either find your way through the menu structure of the tool,
or just enter the name of the setting (or a keyword) into the search field and hit &lt;code&gt;search&lt;&#x2F;code&gt;.
After you&#x27;ve changed a setting, save it by either hitting the &lt;code&gt;state&lt;&#x2F;code&gt; button or the &lt;code&gt;apply and save&lt;&#x2F;code&gt; button at the top of the buffer.
This will make sure your changes get written to your settings file.&lt;&#x2F;p&gt;
&lt;p&gt;Here are a few things I like to customize:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;custom-enabled-themes&lt;&#x2F;code&gt;: select your theme from a list of options&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;inhibit-startup-screen&lt;&#x2F;code&gt;: start with the &lt;code&gt;*scratch*&lt;&#x2F;code&gt; buffer instead of the Emacs startup screen&#x2F;buffer&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;tool-bar-mode&lt;&#x2F;code&gt;: get rid of the tool bar&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;scroll-bar-mode&lt;&#x2F;code&gt;: get rid of the scroll bar&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;package-archives&lt;&#x2F;code&gt;: I&#x27;ve added the repository for stable packages. Hit the &lt;code&gt;ins&lt;&#x2F;code&gt; button and fill out the name (&lt;code&gt;melpa&lt;&#x2F;code&gt;) and the URL (&lt;code&gt;http:&#x2F;&#x2F;stable.melpa.org&#x2F;packages&#x2F;&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You might want to get rid of the menu bar, too.
I kept it because some Emacs commands overlap with Linux system commands (like the command for regular expression search: &lt;code&gt;C-M-s&lt;&#x2F;code&gt;).
I could have solved it differently, but that&#x27;s a personal choice. You might try playing with &lt;code&gt;menu-bar-mode&lt;&#x2F;code&gt; yourself.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bonus-powerline-the-emacs-version-of-the-vim-powerline&quot;&gt;Bonus: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;milkypostman&#x2F;powerline&quot;&gt;Powerline&lt;&#x2F;a&gt;, the Emacs version of the Vim powerline&lt;&#x2F;h2&gt;
&lt;p&gt;If you want to have a fancy Emacs status line, you can start by using the package &lt;code&gt;powerline&lt;&#x2F;code&gt;.
There are other more powerful packages available, but that&#x27;s what we&#x27;ll use here - just for the fun of it.
After you&#x27;ve added the MELPA archive to the list of archives, your Emacs can get the &lt;code&gt;Powerline&lt;&#x2F;code&gt; package from there.
Enter &lt;code&gt;M-x package-install RET powerline&lt;&#x2F;code&gt;. Remember, &lt;code&gt;RET&lt;&#x2F;code&gt; is the return key here.&lt;&#x2F;p&gt;
&lt;p&gt;Now, add the following lines to the start of your settings file (mine was &lt;code&gt;~&#x2F;.emacs.d&#x2F;init.el&lt;&#x2F;code&gt;):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(package-initialize)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;;; Powerline&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(require &amp;#39;powerline)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(powerline-default-theme)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can open this file for editing via Emacs with &lt;code&gt;C-x C-f&lt;&#x2F;code&gt; and then enter the file name: &lt;code&gt;~&#x2F;.emacs.d&#x2F;init.el&lt;&#x2F;code&gt;.
After you&#x27;ve made the changes, save it with &lt;code&gt;C-x C-s&lt;&#x2F;code&gt;. To reload the changes just made,
&lt;code&gt;M-x load-file&lt;&#x2F;code&gt; and press enter twice to accept the default filename, which is the current file being edited.
Alternatively, you can quit Emacs (and restart it later): &lt;code&gt;C-x C-c&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now you can customize the Powerline package: &lt;code&gt;M-x customize&lt;&#x2F;code&gt; and enter &lt;code&gt;powerline&lt;&#x2F;code&gt; in the search field.
All the configurable options of Powerline will appear and can be changed.
As an example, I&#x27;ve changed just one setting: &lt;code&gt;powerline-active1&lt;&#x2F;code&gt;.
I&#x27;m not a fan of colors in the status line, but that&#x27;s me. Feel free to try out every color you like!&lt;&#x2F;p&gt;
&lt;p&gt;If you made all the changes, your Emacs will look a lot like mine.&lt;&#x2F;p&gt;
&lt;p&gt;This story was also published on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;@thomy&#x2F;basic-initial-emacs-customization-d33ed7361835&quot;&gt;Medium&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Statistics challenge and solution</title>
        <published>2017-06-01T00:00:00+00:00</published>
        <updated>2017-06-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/statistics-challenge/"/>
        <id>https://weitzel.dev/blog/statistics-challenge/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/statistics-challenge/">&lt;p&gt;This is a statistics challenge that should be solvable for business analysts.
For reference, an example solution is provided.
The topic is not part of an advanced mathematics course in most federal states of Germany, which is not because it&#x27;s difficult - on the contrary.
The application of the central limit theorem of statistics (CLT) can be helpful in many decision-making processes.&lt;&#x2F;p&gt;
&lt;p&gt;When I was still using Facebook, I wrote it to mock those who posted &lt;em&gt;math riddles&lt;&#x2F;em&gt;. What I learned: they can&#x27;t be mocked - at least not with this.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;challenge&quot;&gt;Challenge&lt;&#x2F;h2&gt;
&lt;p&gt;You work for an international logistics company.
Your company should ship urgent cargo from Munich to Hamburg, 36 boxes from one of your regular customers, but he does not know the weight of the boxes.
Historical records show that the customer&#x27;s boxes weigh 72 kg on average, with a standard deviation of 3 kg.
The only aircraft currently available can hold cargo up to a maximum of 2,630 kg.&lt;&#x2F;p&gt;
&lt;p&gt;Your boss wants to know from you: &lt;strong&gt;what is the probability that the cargo can be transported&lt;&#x2F;strong&gt;?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;solution&quot;&gt;Solution&lt;&#x2F;h2&gt;
&lt;p&gt;The solution is based on the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Central_limit_theorem&quot;&gt;central limit theorem&lt;&#x2F;a&gt;.
It states that if we have a sufficiently large sample $\bar{x}$ of size ${n}$, we can expect the mean
$\mu_ {\bar{x}}$ of this sample to be equal to the average value $\mu_ {x}$ of the customer&#x27;s historical data ${x}$,
and the relation as described under $(2)$ exists between the standard deviation $\sigma_ {x}$ of the customer&#x27;s historical data
and the standard deviation of the sample $\sigma_ {\bar{x}}$.&lt;&#x2F;p&gt;
&lt;p&gt;In addition, the probability density function of the means $\mu_ {\bar{x}}$ of enough samples
$\bar{x}$ of the size ${n}$ approximates the normal distribution $\mathcal{N}(\mu_ {\bar{x}}, \sigma_ {\bar{x}}^{2})$.&lt;&#x2F;p&gt;
&lt;p&gt;This allows us to use the standard normal distribution $\mathcal{N}(0, 1)$ by normalizing.
There exist lookup tables for the standard normal distribution, which saves the calculation.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Since the aircraft takes a maximum of 2,630 kg of cargo, there is a critical mass that must not be exceeded for the average of the boxes: &lt;br &#x2F;&gt;
$(1)$ $$x_{crit} = \frac{2,630\ kg}{36} = 73.06\ kg$$&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;For the mean values and standard deviations: &lt;br &#x2F;&gt;
$(2)$  $$\mu_ {\bar{x}} = \mu_ {x} = 72\ kg, \qquad \sigma_ {\bar{x}} = \frac{\sigma_ {x}}{\sqrt{n}} = \frac{3\ kg}{\sqrt{36}} = 0.5\ kg$$&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;We can get the ${z}$ value for our $x_{crit}$ in $(1)$ from the mean $\mu_ {\bar{x}}$ and the standard deviation $\sigma_ {\bar{x}}$ in $(2)$: &lt;br &#x2F;&gt;
$(3)$  $$z = \frac{x_{crit} - \mu_ {\bar{x}}}{\sigma_ {\bar{x}}} = \frac{73.06\ kg - 72\ kg}{0.5\ kg} = 2.12$$&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The ${z}$ value is our ${x_{crit}}$ converted to its equivalent in the standard normal distribution.
With this value, we can look up the cumulative probability in the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Standard_normal_table&quot;&gt;${z}$ table&lt;&#x2F;a&gt;.
We get $p(2.12) = 0.983$.&lt;&#x2F;p&gt;
&lt;p&gt;This corresponds to a probability of &lt;strong&gt;98.3%&lt;&#x2F;strong&gt; that we have a sample whose mean is 73.06 kg or less.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Fail2ban is your friend</title>
        <published>2016-01-15T00:00:00+00:00</published>
        <updated>2016-01-15T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/syn-fail2ban/"/>
        <id>https://weitzel.dev/blog/syn-fail2ban/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/syn-fail2ban/">&lt;p&gt;For over 20 years, I&#x27;ve been running public servers on the web.
Except for the first year, the operating systems of the servers have always been some Linux variants (Linux is 25 years old right now).
Currently, my server runs &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;releases.ubuntu.com&#x2F;12.04&quot;&gt;Ubuntu 12.04 LTS&lt;&#x2F;a&gt; with &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;plesk.com&quot;&gt;Plesk&lt;&#x2F;a&gt; as server administration software.
It&#x27;s a basic virtual server hosted by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.hosteurope.de&#x2F;en&#x2F;Server&#x2F;Virtual-Server&quot;&gt;Host Europe&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;As soon as I started to look at the log files, I realized that there&#x27;s a lot going on that I would not classify as &quot;intended use&quot; of my server.
It&#x27;s a little like watching the security camera monitoring the front door of your house and seeing a steady stream
of people trying to get in - sometimes by just pressing the door handle, sometimes by trying to run a giant battering ram into it.
Some of them seem just confused. Nevertheless, their strategies might be successful sometimes:
starting at the left edge of the house, they run into the wall, turning around and trying the same one millimeter to the right,
until they finally reach the right edge of the house.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;weitzel.dev&#x2F;blog&#x2F;syn-fail2ban&#x2F;resources&#x2F;media&#x2F;fail2ban-logo.webp&quot; alt=&quot;Scans log files and bans malicious IPs&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A while ago, I decided to do something about it and installed and configured &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.fail2ban.org&quot;&gt;Fail2ban&lt;&#x2F;a&gt; on my server.
The areas that I want to protect are logins via SSH, logins for sending and fetching email, FTP, DNS queries,
and logins to Plesk and WordPress.
There is never 100% guaranteed protection, but reducing server load, log file noise, and risk is worth a try.&lt;&#x2F;p&gt;
&lt;p&gt;Use a guide to learn how to harden your Ubuntu 12.04 LTS server, and read this post to learn
how to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.digitalocean.com&#x2F;community&#x2F;tutorials&#x2F;how-to-protect-ssh-with-fail2ban-on-ubuntu-12-04&quot;&gt;install and do some basic configuration&lt;&#x2F;a&gt;
for Fail2ban.
The rest of this post explains how I configured Fail2ban on my server.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;default-values&quot;&gt;Default values&lt;&#x2F;h2&gt;
&lt;p&gt;The configuration of &lt;code&gt;fail2ban&lt;&#x2F;code&gt; is done in two separate places:
the file &lt;code&gt;&#x2F;etc&#x2F;fail2ban&#x2F;jail.local&lt;&#x2F;code&gt; holds it all together, defines default values,
and references other configuration files (one for each scenario),
while these individual configuration files are located within the directory &lt;code&gt;&#x2F;etc&#x2F;fail2ban&#x2F;filter.d&#x2F;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;My configuration uses log entries from the last &lt;code&gt;findtime&lt;&#x2F;code&gt; seconds (3 hours here) to determine
if there were at least &lt;code&gt;maxretry&lt;&#x2F;code&gt; failed attempts.
In this case, the offending IP address is banned for &lt;code&gt;bantime&lt;&#x2F;code&gt; seconds (3 hours in my case).
What is and what isn&#x27;t a failed attempt is defined in the &lt;code&gt;*.conf&lt;&#x2F;code&gt; files as a regular expression listed under &lt;code&gt;filter&lt;&#x2F;code&gt; for each section.&lt;&#x2F;p&gt;
&lt;p&gt;The list of values under the &lt;code&gt;ignoreip&lt;&#x2F;code&gt; entry (separated by blanks) are the IP addresses
or subnetworks that I want to exclude from all the banning, because I don&#x27;t want to lock myself out:
the local subnetwork is therefore excluded, as is the subnetwork of my own DSL provider (the second address).
The last address is the public IP address of the server itself. All IP addresses are only examples.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;DEFAULT&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ignoreip&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; 127.0.0.1&#x2F;8 123.45.0.0&#x2F;15 67.89.12.34&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;bantime&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span&gt; 10800  &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 3 hours&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;findtime&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span&gt; 10800  &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 3 hours&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;maxretry&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For the following list, the first block is the section in &lt;code&gt;&#x2F;etc&#x2F;fail2ban&#x2F;jail.local&lt;&#x2F;code&gt; that describes the scenario.
The section name, e.g. &lt;code&gt;ssh&lt;&#x2F;code&gt;, will be used as the name of a &lt;code&gt;jail&lt;&#x2F;code&gt;.
A &lt;code&gt;jail&lt;&#x2F;code&gt; is a container for all offending IP addresses that are banned at any given time.
The value for &lt;code&gt;filter&lt;&#x2F;code&gt; is a reference to a configuration file,
e.g. &lt;code&gt;filter = sshd&lt;&#x2F;code&gt; is a reference to the configuration file &lt;code&gt;&#x2F;etc&#x2F;fail2ban&#x2F;filter.d&#x2F;sshd.conf&lt;&#x2F;code&gt;.
And the content of the specific file is then presented after the configuration section of the file &lt;code&gt;&#x2F;etc&#x2F;fail2ban&#x2F;jail.local&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Before you configure a jail, it&#x27;s always a good idea to test it.
&lt;code&gt;Fail2ban&lt;&#x2F;code&gt; has a method to do just that.
For example, if you want to test the jail in section &lt;code&gt;[named]&lt;&#x2F;code&gt;,
you can find the referenced log file and the configuration file and test this combination
with the command &lt;code&gt;fail2ban-regex -v &#x2F;var&#x2F;log&#x2F;daemon.log &#x2F;etc&#x2F;fail2ban&#x2F;filter.d&#x2F;named-refused.conf&lt;&#x2F;code&gt;.
It will output a list of matches for this jail and some other information.
All matches for the regular expressions are shown, regardless of the time they occurred.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ssh-access&quot;&gt;SSH access&lt;&#x2F;h2&gt;
&lt;p&gt;This is probably the service that is attacked the most, often by trying to guess the password for user &lt;code&gt;root&lt;&#x2F;code&gt;.
It&#x27;s always a good idea to disable SSH login by this user.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ssh&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;enabled&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;   =&lt;&#x2F;span&gt;&lt;span&gt; sshd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;action&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;   =&lt;&#x2F;span&gt;&lt;span&gt; iptables[&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;ssh, &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;port&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;ssh, &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;protocol&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;tcp]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;logpath&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;var&#x2F;log&#x2F;auth.log&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Specific configuration file &lt;code&gt;&#x2F;etc&#x2F;fail2ban&#x2F;filter.d&#x2F;sshd.conf&lt;&#x2F;code&gt; looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;INCLUDES&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;before&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; common.conf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Definition&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;_daemon&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; sshd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;failregex&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; ^%(__prefix_line)s(?:error: PAM: )?[aA]uthentication (?:failure|error) for .* from &amp;lt;HOST&amp;gt;( via \S+)?\s*$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            ^%(__prefix_line)s(?:error: PAM: )?User not known to the underlying authentication module for .* from &amp;lt;HOST&amp;gt;\s*$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            ^%(__prefix_line)sFailed \S+ for .*? from &amp;lt;HOST&amp;gt;(?: port \d*)?(?: ssh\d*)?(: (ruser .*|(\S+ ID \S+ \(serial \d+\) CA )?\S+ %(__md5hex)s(, client user &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, client host &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)?))?\s*$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            ^%(__prefix_line)sROOT LOGIN REFUSED.* FROM &amp;lt;HOST&amp;gt;\s*$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            ^%(__prefix_line)s[iI](?:llegal|nvalid) user .* from &amp;lt;HOST&amp;gt;\s*$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            ^%(__prefix_line)sUser .+ from &amp;lt;HOST&amp;gt; not allowed because not listed in AllowUsers\s*$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            ^%(__prefix_line)sUser .+ from &amp;lt;HOST&amp;gt; not allowed because listed in DenyUsers\s*$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            ^%(__prefix_line)sUser .+ from &amp;lt;HOST&amp;gt; not allowed because not in any group\s*$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            ^%(__prefix_line)srefused connect from \S+ \(&amp;lt;HOST&amp;gt;\)\s*$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            ^%(__prefix_line)sReceived disconnect from &amp;lt;HOST&amp;gt;: 3: \S+: Auth fail$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            ^%(__prefix_line)sUser .+ from &amp;lt;HOST&amp;gt; not allowed because a group is listed in DenyGroups\s*$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            ^%(__prefix_line)sUser .+ from &amp;lt;HOST&amp;gt; not allowed because none of user&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s groups are listed in AllowGroups&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;*$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;            ^(?P&amp;lt;__prefix&amp;gt;%(__prefix_line)s)User .+ not allowed because account is locked&amp;lt;SKIPLINES&amp;gt;(?P=__prefix)(?:error: )?Received disconnect from &amp;lt;HOST&amp;gt;: 11: .+ &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;preauth&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\]&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;            ^(?P&amp;lt;__prefix&amp;gt;%(__prefix_line)s)Disconnecting: Too many authentication failures for .+? &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;preauth&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\]&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;lt;SKIPLINES&amp;gt;(?P=__prefix)(?:error: )?Connection closed by &amp;lt;HOST&amp;gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;preauth&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\]&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;            ^(?P&amp;lt;__prefix&amp;gt;%(__prefix_line)s)Connection from &amp;lt;HOST&amp;gt; port &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;+(?: on &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\S&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;+ port &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;+)?&amp;lt;SKIPLINES&amp;gt;(?P=__prefix)Disconnecting: Too many authentication failures for .+? &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;preauth&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\]&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;            ^%(__prefix_line)spam_unix&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;sshd:auth&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\)&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;+authentication failure;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;*logname=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\S&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;*uid=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;*euid=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;*tty=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\S&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;*ruser=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\S&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;*rhost=&amp;lt;HOST&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.*$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;ignoreregex = &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;[Init]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;maxlines = 10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;journalmatch = _SYSTEMD_UNIT=sshd.service + _COMM=sshd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;# Authors: Cyril Jaquier, Yaroslav Halchenko, Petr Voralek, Daniel Black&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;simple-authentication-and-security-layer-sasl&quot;&gt;Simple Authentication and Security Layer (SASL)&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sasl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;enabled&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;port&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;     =&lt;&#x2F;span&gt;&lt;span&gt; smtp,ssmtp,submission,imap2,imap3,imaps,pop3,pop3s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;   =&lt;&#x2F;span&gt;&lt;span&gt; postfix-sasl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;action&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;   =&lt;&#x2F;span&gt;&lt;span&gt; iptables[&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;sasl, &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;port&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;smtp, &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;protocol&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;tcp]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;logpath&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;var&#x2F;log&#x2F;maillog&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Specific configuration file &lt;code&gt;&#x2F;etc&#x2F;fail2ban&#x2F;filter.d&#x2F;postfix-sasl.conf&lt;&#x2F;code&gt; looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;INCLUDES&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;before&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; common.conf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Definition&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;_daemon&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; postfix&#x2F;(submission&#x2F;)?smtp(d|s)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;failregex&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; ^%(__prefix_line)swarning: [-._\w]+\[&amp;lt;HOST&amp;gt;\]: SASL ((?i)LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed(: [ A-Za-z0-9+&#x2F;:]*={0,2})?\s*$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ignoreregex&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; authentication failed: Connection lost to authentication server$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Init&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;journalmatch&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; _SYSTEMD_UNIT&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;postfix.service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Author: Yaroslav Halchenko&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;file-transfer-via-ftp&quot;&gt;File Transfer via FTP&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;proftp&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;enabled&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;   =&lt;&#x2F;span&gt;&lt;span&gt; proftpd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;action&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;   =&lt;&#x2F;span&gt;&lt;span&gt; iptables[&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;proftp, &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;port&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;ftp, &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;protocol&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;tcp]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;logpath&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;var&#x2F;log&#x2F;auth.log&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Specific configuration file &lt;code&gt;&#x2F;etc&#x2F;fail2ban&#x2F;filter.d&#x2F;proftpd.conf&lt;&#x2F;code&gt; looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;INCLUDES&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;before&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; common.conf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Definition&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;_daemon&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; proftpd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;__suffix_failed_login&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (User not authorized for login|No such user found|Incorrect password|Password expired|Account disabled|Invalid shell: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt;\S&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;|User in \S+|Limit (access|configuration) denies login|Not a UserAlias|maximum login length exceeded).?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;failregex&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; ^%(__prefix_line)s%(__hostname)s \(\S+\[&amp;lt;HOST&amp;gt;\]\)[: -]+ USER .*: no such user found from \S+ \[\S+\] to \S+:\S+ *$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            ^%(__prefix_line)s%(__hostname)s \(\S+\[&amp;lt;HOST&amp;gt;\]\)[: -]+ USER .* \(Login failed\): %(__suffix_failed_login)s\s*$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            ^%(__prefix_line)s%(__hostname)s \(\S+\[&amp;lt;HOST&amp;gt;\]\)[: -]+ SECURITY VIOLATION: .* login attempted\. *$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            ^%(__prefix_line)s%(__hostname)s \(\S+\[&amp;lt;HOST&amp;gt;\]\)[: -]+ Maximum login attempts \(\d+\) exceeded *$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ignoreregex&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Authors: Yaroslav Halchenko, Daniel Black&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;fetching-email&quot;&gt;Fetching email&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;courier&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;enabled&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;   =&lt;&#x2F;span&gt;&lt;span&gt; courier-login&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;action&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;   =&lt;&#x2F;span&gt;&lt;span&gt; iptables-multiport[&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;courier, &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;port&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;110,995,143,993&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;protocol&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;tcp]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;logpath&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;var&#x2F;log&#x2F;maillog&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Specific configuration file &lt;code&gt;&#x2F;etc&#x2F;fail2ban&#x2F;filter.d&#x2F;courier-login.conf&lt;&#x2F;code&gt; looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;INCLUDES&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;before&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; common.conf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Definition&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;_daemon&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (?:courier)?(?:imapd?|pop3d?)(?:login)?(?:-ssl)?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;failregex&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; courier-[A-z0-9]+: LOGIN FAILED, &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;user&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;.*, &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;ip&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;\[&amp;lt;HOST&amp;gt;\]$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ignoreregex&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Author: Unknown&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;dns&quot;&gt;DNS&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;named&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;enabled&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;   =&lt;&#x2F;span&gt;&lt;span&gt; named-refused&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;action&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;   =&lt;&#x2F;span&gt;&lt;span&gt; iptables-multiport[&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;named, &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;port&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;53,953&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;protocol&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;tcp]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;logpath&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;var&#x2F;log&#x2F;daemon.log&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Specific configuration file &lt;code&gt;&#x2F;etc&#x2F;fail2ban&#x2F;filter.d&#x2F;named-refused.conf&lt;&#x2F;code&gt; looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Definition&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;_daemon&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;named&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;__pid_re&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;(?:\[\d+\])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;__daemon_re&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;\(?%(_daemon)s(?:\(\S+\))?\)?:?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;__daemon_combs_re&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;(?:%(__pid_re)s?:\s+%(__daemon_re)s|%(__daemon_re)s%(__pid_re)s?:)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;__line_prefix&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;(?:\s\S+ %(__daemon_combs_re)s\s+)?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;failregex&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; ^%(__line_prefix)s( error:)?\s*client &amp;lt;HOST&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;\S+( \([\S.]+\))?: (view (internal|external): )?query(?: \(cache\))? &amp;#39;.*&amp;#39; denied\s*$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            ^%(__line_prefix)s( error:)?\s*client &amp;lt;HOST&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;\S+( \([\S.]+\))?: zone transfer &amp;#39;\S+&#x2F;AXFR&#x2F;\w+&amp;#39; denied\s*$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            ^%(__line_prefix)s( error:)?\s*client &amp;lt;HOST&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;\S+( \([\S.]+\))?: bad zone transfer request: &amp;#39;\S+&#x2F;IN&amp;#39;: non-authoritative zone \(NOTAUTH\)\s*$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;\(NOTAUTH\)\s*$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ignoreregex&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Author: Yaroslav Halchenko&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;plesk-access&quot;&gt;Plesk access&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;plesk&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;enabled&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;   =&lt;&#x2F;span&gt;&lt;span&gt; plesk-login&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;action&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;   =&lt;&#x2F;span&gt;&lt;span&gt; iptables-multiport[&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;plesk, &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;port&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;80,443,8443&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;protocol&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;tcp]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;logpath&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;var&#x2F;log&#x2F;plesk&#x2F;panel.log&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Specific configuration file &lt;code&gt;&#x2F;etc&#x2F;fail2ban&#x2F;filter.d&#x2F;plesk-login.conf&lt;&#x2F;code&gt; looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;INCLUDES&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;before&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; common.conf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Definition&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;failregex&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; Failed login attempt with login &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; from IP &amp;lt;HOST&amp;gt;$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ignoreregex&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Author: Thomas Weitzel&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;wordpress-administration&quot;&gt;WordPress administration&lt;&#x2F;h2&gt;
&lt;p&gt;As a prerequisite, I&#x27;ve installed a plugin on all of my WordPress sites
that helps &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;timnash.co.uk&#x2F;using-fail2ban-wordpress&quot;&gt;prevent brute force attacks with Fail2ban &amp;amp; WordPress&lt;&#x2F;a&gt;.
This plugin makes sure that failed login attempts are easily found within the log files.
Additionally, login into WordPress should only be possible via &lt;code&gt;HTTPS&lt;&#x2F;code&gt;.
Adding the following lines to your &lt;code&gt;wp-config.php&lt;&#x2F;code&gt; will make sure that nobody can log in without using &lt;code&gt;SSL&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Force SSL login for administrator&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;define&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;FORCE_SSL_ADMIN&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-language&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;One little remark regarding the use of SSL certificates: since the end of 2015
I use free &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;letsencrypt.org&quot;&gt;Let&#x27;s Encrypt&lt;&#x2F;a&gt; certificates.
Highly recommended.
These certificates are trusted by most browsers.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;wordpress&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;enabled&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;port&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;     =&lt;&#x2F;span&gt;&lt;span&gt; http,https&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;   =&lt;&#x2F;span&gt;&lt;span&gt; wordpress-auth&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;action&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;   =&lt;&#x2F;span&gt;&lt;span&gt; iptables[&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;wpauth, &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;port&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;https, &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;protocol&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;tcp]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;logpath&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;var&#x2F;www&#x2F;vhosts&#x2F;domain1.org&#x2F;logs&#x2F;access_ssl_log&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           &#x2F;var&#x2F;www&#x2F;vhosts&#x2F;domain2.org&#x2F;logs&#x2F;access_ssl_log&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           &#x2F;var&#x2F;www&#x2F;vhosts&#x2F;domain3.org&#x2F;logs&#x2F;access_ssl_log&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Specific configuration file &lt;code&gt;&#x2F;etc&#x2F;fail2ban&#x2F;filter.d&#x2F;wordpress-auth.conf&lt;&#x2F;code&gt; looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;INCLUDES&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;before&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; common.conf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Definition&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;failregex&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; ^&amp;lt;HOST&amp;gt;\s.*POST.*(wp-login\.php|xmlrpc\.php).* 401&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ignoreregex&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Author: Tim Nash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;handling-persistent-disruptors&quot;&gt;Handling persistent disruptors&lt;&#x2F;h2&gt;
&lt;p&gt;This is a special case: &lt;code&gt;Fail2ban&lt;&#x2F;code&gt; can monitor its own log file.
This feature can be used to find repeating offenders and treat them in a unique way.
In my case, if an IP address gets banned for a second time within a week (remember, I ban it only for 3 hours the first time),
it gets banned for an entire week.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;recidive&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;enabled&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;   =&lt;&#x2F;span&gt;&lt;span&gt; recidive&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;action&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;   =&lt;&#x2F;span&gt;&lt;span&gt; iptables-allports[&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;recidive]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;logpath&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;var&#x2F;log&#x2F;fail2ban.log&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;bantime&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span&gt; 604800  &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 1 week&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;findtime&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; 604800  &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 1 week&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;maxretry&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Specific configuration file &lt;code&gt;&#x2F;etc&#x2F;fail2ban&#x2F;filter.d&#x2F;recidive.conf&lt;&#x2F;code&gt; looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;INCLUDES&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;before&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; common.conf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Definition&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;_daemon&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; fail2ban\.actions\s*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;_jailname&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; recidive&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;failregex&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; ^(%(__prefix_line)s| %(_daemon)s%(__pid_re)s?:\s+)NOTICE\s+\[(?!%(_jailname)s\])(?:.*)\]\s+Ban\s+&amp;lt;HOST&amp;gt;\s*$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ignoreregex&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Init&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;journalmatch&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; _SYSTEMD_UNIT&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;fail2ban.service &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;PRIORITY&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Authors: Tom Hendrikx, Amir Caspi &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;While &lt;code&gt;Fail2ban&lt;&#x2F;code&gt; is not the highest hurdle to take, it handles at least most of the script kiddies very well.
And these are making up the majority of my log messages.
It is one of a series of steps that you should take to make your own server a little more secure.&lt;&#x2F;p&gt;
&lt;p&gt;The contents of the individual configuration files have accumulated on my server over time.
They are nearly entirely the work of others, and I&#x27;ve just used their work.
If you are one of the original authors: &lt;strong&gt;Thank you!&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Integrating Tomcat and Apache on Mint Linux</title>
        <published>2014-07-27T00:00:00+00:00</published>
        <updated>2014-07-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/syn-integrating-tomcat/"/>
        <id>https://weitzel.dev/blog/syn-integrating-tomcat/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/syn-integrating-tomcat/">&lt;p&gt;On May 31st, 2014, the Linux distribution &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.linuxmint.com&quot;&gt;Linux Mint&lt;&#x2F;a&gt; 17 (named &quot;Qiana&quot;) Cinnamon was released.
Since I wanted to replace &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.ubuntu.com&quot;&gt;Ubuntu Linux&lt;&#x2F;a&gt; on my Lenovo ThinkPad with something else
(but nothing too far away from it), I chose Mint Cinnamon (64-bit).
Installation was easy and fast, but then I had to redo the installation of my CMS synformation on that machine
(simply because I use it as a development and test machine).
Java 1.7 (OpenJDK) was installed already, so I had to install Tomcat, MySQL, and Apache.
Here, I&#x27;ll only talk about Tomcat and Apache, because I chose to use another way to integrate both:
I had used &lt;code&gt;mod_jk&lt;&#x2F;code&gt; before and was looking for an easier way.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;weitzel.dev&#x2F;blog&#x2F;syn-integrating-tomcat&#x2F;resources&#x2F;media&#x2F;mint-apache-tomcat.webp&quot; alt=&quot;Logo Compilation&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;There are several ways to integrate Tomcat and Apache:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Proxy (which I will use)&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
Proxy is more transparent than other methods and works with either the HTTP protocol or the Apache JServ Protocol (AJP).
AJP is a binary communication protocol and has better performance than HTTP.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;mod_jk&lt;&#x2F;code&gt; (which I used before, but found it overly complex)&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
Integration through &lt;code&gt;mod_jk&lt;&#x2F;code&gt; is a more advanced way of integrating Tomcat and Apache.
It provides additional features like load balancing and failure detection.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Maybe there are other ways I don&#x27;t know about or wouldn&#x27;t consider.&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;integration-with-the-proxy-module&quot;&gt;Integration with the proxy module&lt;&#x2F;h2&gt;
&lt;p&gt;You need to open a terminal window in order to execute the following commands.&lt;&#x2F;p&gt;
&lt;p&gt;Install Apache and Tomcat (with the manager application, which is needed later as a test case):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; apt-get&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; install&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; apache2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; tomcat7&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; tomcat7-admin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Enabling Apache module &lt;code&gt;proxy_http&lt;&#x2F;code&gt; and &lt;code&gt;proxy_ajp&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; a2enmod&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; proxy_http&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; a2enmod&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; proxy_ajp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If it&#x27;s already enabled, you get something like the following message:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Considering dependency proxy for proxy_http:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Module proxy already enabled&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Module proxy_http already enabled&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now you can use either HTTP or AJP for integrating Tomcat and Apache.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;a-using-http&quot;&gt;A. Using HTTP&lt;&#x2F;h3&gt;
&lt;p&gt;Edit the file &lt;code&gt;&#x2F;etc&#x2F;apache2&#x2F;sites-enabled&#x2F;000-default.conf&lt;&#x2F;code&gt; (or whatever &lt;code&gt;.conf&lt;&#x2F;code&gt; file for one of your sites you want to use) and add at the bottom:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;apache&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Needs &amp;quot;proxy_module&amp;quot; and &amp;quot;proxy_http_module&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;location &#x2F;manager&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;  # Local server (Tomcat via http)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  ProxyPass&lt;&#x2F;span&gt;&lt;span&gt; http:&#x2F;&#x2F;localhost:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;8080&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;manager&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  ProxyPassReverse&lt;&#x2F;span&gt;&lt;span&gt; http:&#x2F;&#x2F;localhost:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;8080&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;manager&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&#x2F;location&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you want to use AJP instead of HTTP, follow section B.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;b-using-ajp&quot;&gt;B. Using AJP&lt;&#x2F;h3&gt;
&lt;p&gt;You have to enable the AJP connector in Tomcat&#x27;s &lt;code&gt;server.xml&lt;&#x2F;code&gt; (&lt;code&gt;&#x2F;etc&#x2F;tomcat7&#x2F;server.xml&lt;&#x2F;code&gt;, the line is there but commented out; activate the line):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;apache&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;connector port=&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;8009&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; protocol=&amp;quot;AJP&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot; redirectPort=&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;8443&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&amp;gt;&amp;lt;&#x2F;connector&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Edit the file &lt;code&gt;&#x2F;etc&#x2F;apache2&#x2F;sites-enabled&#x2F;000-default.conf&lt;&#x2F;code&gt; and add at the bottom:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;apache&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;# Needs &amp;quot;proxy_module&amp;quot; and &amp;quot;proxy_ajp_module&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;location &#x2F;manager&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;  # Local server (Tomcat via ajp)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  ProxyPass&lt;&#x2F;span&gt;&lt;span&gt; ajp:&#x2F;&#x2F;localhost:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;8009&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;manager&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  ProxyPassReverse&lt;&#x2F;span&gt;&lt;span&gt; ajp:&#x2F;&#x2F;localhost:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-numeric&quot;&gt;8009&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;manager&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&#x2F;location&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you want to actually work with the manager application, you have to configure roles and at least one user for Tomcat. Edit the file &lt;code&gt;&#x2F;etc&#x2F;tomcat7&#x2F;tomcat-users.xml&lt;&#x2F;code&gt; and make the element &lt;code&gt;&amp;lt;tomcat-users&amp;gt;&lt;&#x2F;code&gt; look like this (you should try to come up with a more original password than I have):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;tomcat-users&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;role&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt; rolename&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;manager-gui&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;role&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;role&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt; rolename&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;manager&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;role&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;role&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt; rolename&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;admin-gui&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;role&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;role&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt; rolename&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;admin&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;role&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;user&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt; username&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;admin&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt; password&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;admin&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name&quot;&gt; roles&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;manager-gui,admin-gui,manager,admin&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;user&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;tomcat&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Don&#x27;t forget to restart Apache after you make configuration changes:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;etc&#x2F;init.d&#x2F;apache2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; restart&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Same goes for Tomcat:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;etc&#x2F;init.d&#x2F;tomcat7&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; restart&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To access the manager application through Tomcat (and not Apache),
you would use &lt;code&gt;http:&#x2F;&#x2F;localhost:8080&#x2F;manager&lt;&#x2F;code&gt;.
But now it&#x27;s time to try out the path via Apache and then Tomcat:
visit &lt;code&gt;http:&#x2F;&#x2F;localhost&#x2F;manager&lt;&#x2F;code&gt; in your favorite web browser
and log in with the user &lt;code&gt;admin&lt;&#x2F;code&gt; and the password you&#x27;ve defined (mine from the example was &lt;code&gt;admin&lt;&#x2F;code&gt;).
Does it work?&lt;&#x2F;p&gt;
&lt;p&gt;If you have other web applications installed in Tomcat, you can access them via Apache, too.
Simply add more &lt;code&gt;&amp;lt;location&amp;gt;&lt;&#x2F;code&gt; elements to your Apache configuration.&lt;&#x2F;p&gt;
&lt;p&gt;In a production environment,
I would recommend using the AJP connector and disabling the Tomcat HTTP connector in the file &lt;code&gt;&#x2F;etc&#x2F;tomcat7&#x2F;server.xml&lt;&#x2F;code&gt;,
so all traffic has to go through Apache.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Social date and time formatting</title>
        <published>2014-07-25T00:00:00+00:00</published>
        <updated>2014-07-25T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/pretty-time/"/>
        <id>https://weitzel.dev/blog/pretty-time/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/pretty-time/">&lt;p&gt;I don&#x27;t say &quot;when I was on vacation on May 25th, 2013 at 12:13, I enjoyed it&quot;. What I really enjoyed was my vacation last year.
It&#x27;s the same with comments for blog posts. We do not need the exact date and time a comment was posted.&lt;&#x2F;p&gt;
&lt;p&gt;In 2009, I was looking for a Java library for a data warehouse project at a bank that displays time differences in a friendly way.
As we say: &quot;10 minutes ago&quot;, &quot;5 years ago&quot; or &quot;in 2 weeks&quot; instead of &quot;2 hours, 37 minutes and 11 seconds ago&quot; or &quot;17 August 2001&quot; - unless it&#x27;s
a rocket launch or a private anniversary whose exact date should not be forgotten.
I found what I was looking for with the open-source project &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.ocpsoft.org&#x2F;prettytime&#x2F;&quot;&gt;PrettyTime&lt;&#x2F;a&gt;.
Unfortunately, only English was supported at that time.
I had to make the changes necessary to support German, because that was the language used for our project.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;kotlin&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-entity z-name z-package&quot;&gt; org.ocpsoft.prettytime.PrettyTime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;val&lt;&#x2F;span&gt;&lt;span&gt; pt &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; PrettyTime&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;val&lt;&#x2F;span&gt;&lt;span&gt; ptString &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; pt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;format&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Date&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;moments from now&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The author was looking for someone to make his library fit for other languages.
The requirement was that language resources can be easily stored on the classpath.
The language should either be automatically recognized depending on the current locale, or set programmatically.
Since I had made the language-specific adjustments already, I made them available for PrettyTime.&lt;&#x2F;p&gt;
&lt;p&gt;When you write a comment for one of the posts on this blog, the time difference will be displayed with the help of PrettyTime.
Go ahead, try it for yourself.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Trac for a team of one</title>
        <published>2007-09-10T00:00:00+00:00</published>
        <updated>2007-09-10T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/syn-trac-team/"/>
        <id>https://weitzel.dev/blog/syn-trac-team/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/syn-trac-team/">&lt;p&gt;Even the smallest development team (one developer) needs a source code repository with versioning like Subversion to
track all the changes made to the source code over time, and to reproduce the revisions that software releases were based on.
The ability to create branches is necessary to maintain software releases in the field,
while continuing with development at the same time.
If you think you don&#x27;t need it, you probably don&#x27;t know enough about it (in a couple of really rare cases,
you might indeed not need it, but even then it really doesn&#x27;t hurt).
For most developers, working with a source code repository is as natural as working with an IDE like &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.eclipse.org&quot;&gt;Eclipse&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Even though small development teams use a version system in many cases, an issue tracking system is used to a much lesser extent.
But I believe that it&#x27;s quite as important as having something like Subversion, because it makes the developer&#x27;s life so much easier.
I have just experienced it while working in a small team during my current project.
And there are solutions out there that are easy to install and maintain.
One (and one of the easiest and best) is &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;trac.edgewall.org&quot;&gt;Trac&lt;&#x2F;a&gt;:
Trac is an integrated software configuration (and project) management system (SCM).
It&#x27;s an issue tracking system for software development projects with an integrated wiki.
Basically, it&#x27;s a project management suite that includes a wiki, a bug&#x2F;issue tracking system,
and a source control viewer that accesses a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;subversion.apache.org&#x2F;&quot;&gt;Subversion&lt;&#x2F;a&gt; repository.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;weitzel.dev&#x2F;blog&#x2F;syn-trac-team&#x2F;resources&#x2F;media&#x2F;tracxmlrpc.webp&quot; alt=&quot;Screenshot of Trac XML-RPC plugin working with Eclipse and Mylyn&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Since developers always tend to try out the newest and latest (I&#x27;m no exception to this rule,
nor do I want to disappoint you), I&#x27;ve installed the Trac version currently under development (0.11dev).
The integration with the Eclipse development environment also requires the latest development version of the Trac XML-RPC plugin.
This is what you should have installed already:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Eclipse development platform with Mylyn Trac Connector.&lt;&#x2F;li&gt;
&lt;li&gt;Working Subversion (SVN) installation.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.python.org&quot;&gt;Python&lt;&#x2F;a&gt; is installed on your system (Trac is written in Python).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;peak.telecommunity.com&#x2F;DevCenter&#x2F;EasyInstall&quot;&gt;easy_install&lt;&#x2F;a&gt; is available.&lt;&#x2F;li&gt;
&lt;li&gt;It helps if you have installed an older version of Trac (e.g. 0.10.4) once.
If you don&#x27;t have any experience with Trac, you should go &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;trac.edgewall.org&quot;&gt;there&lt;&#x2F;a&gt; and read their documentation.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Now install Trac and the Trac XML-RPC plugin:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Checkout the latest development sources from Trac: &lt;code&gt;http:&#x2F;&#x2F;svn.edgewall.org&#x2F;repos&#x2F;trac&#x2F;trunk&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Install&#x2F;update Trac from the &lt;code&gt;trunk&lt;&#x2F;code&gt; directory: &lt;code&gt;$ python setup.py install&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Checkout the sources from the Trac XML-RPC plugin: &lt;code&gt;http:&#x2F;&#x2F;trac-hacks.org&#x2F;svn&#x2F;xmlrpcplugin&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Install or update the Trac XML-RPC plugin as described &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;trac-hacks.org&#x2F;wiki&#x2F;XmlRpcPlugin&quot;&gt;here&lt;&#x2F;a&gt;: &lt;code&gt;$ easy_install trunk&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Edit &lt;code&gt;trac.ini&lt;&#x2F;code&gt; and add (under &lt;code&gt;[components]&lt;&#x2F;code&gt;) &lt;code&gt;tracrpc.* = enabled&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Start (or restart) Trac, e.g. via &lt;code&gt;tracd&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You can now access and create your Trac tickets from within Eclipse with the help of the Mylyn Trac Connector.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Programming editors</title>
        <published>2007-02-01T00:00:00+00:00</published>
        <updated>2007-02-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/syn-programming-editors/"/>
        <id>https://weitzel.dev/blog/syn-programming-editors/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/syn-programming-editors/">&lt;p&gt;Everyone who programs uses one or more of them.
My favorite programming editor is Epsilon from &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;lugaru.com&quot;&gt;Lugaru Software Ltd.&lt;&#x2F;a&gt;, and has been since 1996.
It’s been around since 1984.
Although my first version was for DOS, Windows, and OS&#x2F;2, I used it primarily under DOS for writing C programs.
I started in 1978 with a BASIC dialect and 8080&#x2F;Z80 assembler on a Sord M203 mark II computer.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;weitzel.dev&#x2F;blog&#x2F;syn-programming-editors&#x2F;resources&#x2F;media&#x2F;sord-m203-mark-ii.webp&quot; alt=&quot;Sord M203 Mark II computer&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I wasn&#x27;t thinking about what editor to use back then, because there was no choice.
I had to use the one that came with this Sord computer.
A little later I switched to C and then C++, followed by Java in 1996.
There will be something after Java, but I can&#x27;t see it yet.
It&#x27;s not so much the programming language itself that keeps me, but the Java platform.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;weitzel.dev&#x2F;blog&#x2F;syn-programming-editors&#x2F;resources&#x2F;media&#x2F;epsilon.webp&quot; alt=&quot;Screenshot from Epsilon editor under Windows&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Epsilon is an &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;emacs&quot;&gt;Emacs&lt;&#x2F;a&gt; clone, but unlike Emacs,
which can be extended with Lisp code, Epsilon uses a C-like language called EEL (Epsilon extension language).
As you can see from the list of programming languages I&#x27;m familiar enough with, Lisp isn&#x27;t on it, but C is.
Although this short enumeration of programming languages isn&#x27;t complete,
I haven&#x27;t used any of the others for a significant amount of time.
It&#x27;s important for me that Epsilon is programmable in a language I&#x27;m fluent in.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s one exception to my otherwise consistent use of Epsilon.
When it comes to Java programming, I&#x27;m using Eclipse most of the time.
Not always, because some things I still do with Epsilon, but most of the things are a little easier within Eclipse.&lt;&#x2F;p&gt;
&lt;p&gt;During the time I worked with Epsilon, I observed a strange thing:
some programmers (even brilliant ones) worked with editors that do not support them well with their work.
Even when shown alternative editors that would support them much more,
they gave up early on learning the features of the new tool.
Instead, they spend hours writing some small utility programs for tasks that are possible within minutes for editors like Epsilon.
Instead of investing the time in learning a new tool,
they spend much more time fixing the shortcomings of the editors they were used to.&lt;&#x2F;p&gt;
&lt;p&gt;Don&#x27;t get me wrong, Epsilon is not a panacea for everything, and I&#x27;m gone the minute I find something better.
But in the past 10 years, I haven&#x27;t.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>A night at Frankfurt airport</title>
        <published>2006-12-30T00:00:00+00:00</published>
        <updated>2006-12-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            Thomas Weitzel
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weitzel.dev/blog/syn-night-at-airport/"/>
        <id>https://weitzel.dev/blog/syn-night-at-airport/</id>
        
        <content type="html" xml:base="https://weitzel.dev/blog/syn-night-at-airport/">&lt;p&gt;Yesterday, I received a phone call from someone who asked me to meet aircraft N279WA in
&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Frankfurt_International_Airport&quot;&gt;Frankfurt&lt;&#x2F;a&gt; on a cargo mission.
It came from Chicago and went back to Atlanta.
This aircraft has been converted to a cargo plane only recently, and it has a new livery now.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;weitzel.dev&#x2F;blog&#x2F;syn-night-at-airport&#x2F;resources&#x2F;media&#x2F;n279wa.webp&quot; alt=&quot;Aircraft N279WA during pushback from position F215&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Before, it was a passenger aircraft. I knew it mostly from &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.amc.af.mil&quot;&gt;Air Mobility Command&lt;&#x2F;a&gt; missions.
On several occasions, I flew with it from the now defunct &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.af.mil&#x2F;news&#x2F;story.asp?storyID=123011993&quot;&gt;Rhein-Main AFB&lt;&#x2F;a&gt;
to &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.globalsecurity.org&#x2F;military&#x2F;facility&#x2F;udeid.htm&quot;&gt;Al Udeid AFB&lt;&#x2F;a&gt; in Qatar.
Most flights went through Bahrain airport, because the commercial air carriers need a place to change crews and get catering.
This is difficult to accomplish on some Air Force Bases, but certainly in Al Udeid.
The AMC missions are still going on, but without this aircraft.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;weitzel.dev&#x2F;blog&#x2F;syn-night-at-airport&#x2F;resources&#x2F;media&#x2F;n279wa-main-deck.webp&quot; alt=&quot;Empty main deck&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;While I was there, I took some pictures, one from the main deck after unloading the inbound cargo.
The main deck alone on this MD-11 can hold more than 150,000 lbs of cargo.
Loading teams in Frankfurt regularly load an entire MD-11 cargo aircraft in 45 to 60 minutes.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;weitzel.dev&#x2F;blog&#x2F;syn-night-at-airport&#x2F;resources&#x2F;media&#x2F;n279wa-cockpit.webp&quot; alt=&quot;Me in the cockpit&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Here you can see a portion of the N279WA cockpit from that night, with me in the captain’s seat.
Although I know how to read and use some instruments,
I can barely fly an aircraft with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.xbox.com&#x2F;en-US&#x2F;games&#x2F;microsoft-flight-simulator&quot;&gt;Microsoft&#x27;s Flight Simulator&lt;&#x2F;a&gt;.
But then, this isn&#x27;t my job.&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
