<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
      <title>sergiu.org</title>
      <link>https://sergiu.org</link>
      <description></description>
      <generator>Zola</generator>
      <language>en</language>
      <atom:link href="https://sergiu.org/rss.xml" rel="self" type="application/rss+xml"/>
      <lastBuildDate>Thu, 06 Jan 2022 00:00:00 +0000</lastBuildDate>
      <item>
          <title>Things I want to 3D print</title>
          <pubDate>Thu, 06 Jan 2022 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://sergiu.org/blog/things-i-want-to-3d-print/</link>
          <guid>https://sergiu.org/blog/things-i-want-to-3d-print/</guid>
          <description xml:base="https://sergiu.org/blog/things-i-want-to-3d-print/">&lt;p&gt;In no particular order:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A mini Simpsons TV (inspired from &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;withrow.io&#x2F;simpsons-tv-build-guide&quot;&gt;this&lt;&#x2F;a&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;A working &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Curta&quot;&gt;Curta calculator&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Board game organizers, dice, familiars, trays, etc.&lt;&#x2F;li&gt;
&lt;li&gt;A miniature model of my head based on 3d scans.&lt;&#x2F;li&gt;
&lt;li&gt;Replacement headband for my broken headphones.&lt;&#x2F;li&gt;
&lt;li&gt;A small scale replica of my home.&lt;&#x2F;li&gt;
&lt;li&gt;Auto-agitator for the Lab Box.
&lt;img src=&quot;https:&#x2F;&#x2F;sergiu.org&#x2F;blog&#x2F;things-i-want-to-3d-print&#x2F;Lab-Box_Modular_Web.jpg&quot; alt=&quot;Lab Box&quot; &#x2F;&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Google Home Mini wall holder
&lt;img src=&quot;https:&#x2F;&#x2F;sergiu.org&#x2F;blog&#x2F;things-i-want-to-3d-print&#x2F;8y9ks58ug0a41.jpg&quot; alt=&quot;Google Home&quot; &#x2F;&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Programmable curtain&#x2F;blinds controller.&lt;&#x2F;li&gt;
&lt;li&gt;HDD rack for home server.&lt;&#x2F;li&gt;
&lt;li&gt;Spring loaded caliper case.&lt;&#x2F;li&gt;
&lt;li&gt;Alphabet shelf separators for organizing vinyl records.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
      </item>
      <item>
          <title>Project Euler #213: Flea Circus</title>
          <pubDate>Wed, 06 Oct 2021 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://sergiu.org/blog/euler-213/</link>
          <guid>https://sergiu.org/blog/euler-213/</guid>
          <description xml:base="https://sergiu.org/blog/euler-213/">&lt;blockquote&gt;
&lt;p&gt;A $30 \times 30$ grid of squares contains 900 fleas, initially one flea per square.
When a bell is rung, each flea jumps to an adjacent square at random (usually 4 possibilities, except for fleas on the edge of the grid or at the corners).&lt;&#x2F;p&gt;
&lt;p&gt;What is the expected number of unoccupied squares after 50 rings of the bell? Give your answer rounded to six decimal places.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The problem statement looks deceivingly simple but also doesn’t give away any approach towards finding a solution. The entire process can be simulated using the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Monte_Carlo_method&quot;&gt;Monte Carlo method&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;place one flea in each cell of an $ n \times n $ grid ($ n = 30 $)&lt;&#x2F;li&gt;
&lt;li&gt;simulate $ k = 50 $ bell rings
&lt;ul&gt;
&lt;li&gt;during each bell ring, move all $ 900 $ fleas to a randomly selected neighboring cell&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;count the number of empty cells at the end&lt;&#x2F;li&gt;
&lt;li&gt;repeat the whole process as many times as possible and average the results&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This can give a reasonable approximation of the final result but is in no way feasible considering the required precision. A straight-forward implementation can simulate one experiment in  $ O(n^2 \cdot k) $, which is already a non-trivial complexity. My C++ implementation needs almost a minute to simulate the experiment $ 10^5 $ times. The precision is not great: at most one significant figure, and only some of the time. Increasing the iteration count to $ 10^6 $ does not necessarily perform better. There is still a high variance between runs.&lt;&#x2F;p&gt;
&lt;p&gt;But at least we have a better idea of what the answer looks like:&lt;&#x2F;p&gt;
&lt;center&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https:&#x2F;&#x2F;www.youtube-nocookie.com&#x2F;embed&#x2F;_gOsLi2-MC0?autoplay=1&amp;loop=1&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;&lt;&#x2F;iframe&gt;
&lt;&#x2F;center&gt;
&lt;h2 id=&quot;expected-value&quot;&gt;Expected value&lt;a class=&quot;zola-anchor&quot; href=&quot;#expected-value&quot; aria-label=&quot;Anchor link for: expected-value&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The expected number of unoccupied cells is, simply put, the average that would be obtained by repeating the simulation infinitely many times. Mathematically, it is a weighted arithmetic mean of the possible outcomes (i.e. number of unoccupied cells) and the probabilities of obtaining them.&lt;&#x2F;p&gt;
&lt;p&gt;If we denote the discrete random variable $ X $ to represent the number of unoccupied cells after 50 bell rings, then:&lt;&#x2F;p&gt;
&lt;p&gt;$$ E(X) = \sum x_i p_i $$&lt;&#x2F;p&gt;
&lt;p&gt;where the values $ x_i $ are the possible outcomes $ X $.&lt;&#x2F;p&gt;
&lt;p&gt;In practice, we know what these outcomes are. The two extremes are $ x_{min} = 1 $ (all fleas end up in exactly the same cell) and $ x_{max} = 900 $ (all fleas end up in distinct cells, exactly like the beginning). Every value in between is also plausible.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;probabilities&quot;&gt;Probabilities&lt;a class=&quot;zola-anchor&quot; href=&quot;#probabilities&quot; aria-label=&quot;Anchor link for: probabilities&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Now we need a way to compute any given probability $ p_i $ of ending up with exactly $ i $ unoccupied cells. We can draw some intuitive conclusions right away: it’s highly likely that $ p $ follows a bell curve. Moreover, it might be more likely for border and corner cells to be empty. They have fewer neighbors where fleas can enter from, and border fleas can only stay for so long before the randomness pulls them closer to the center. I have no proof for either of these claims but it might be fun to plot some graphs and verify them.&lt;&#x2F;p&gt;
&lt;p&gt;In any case, the probability is tricky to compute. Since this looks a lot like a counting problem, maybe a dynamic programming approach can work. I tried to come up with a useful definition, going through several iterations depending on the information that was needed:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;$ dp(i,j,k) = $ the probability of having cell $(i, j)$ occupied after $k$ bells.&lt;&#x2F;li&gt;
&lt;li&gt;Initial state: $ dp(i,j,0) = 1 $. Every cell is occupied in the beginning.&lt;&#x2F;li&gt;
&lt;li&gt;Recurrence: hard to tell. Since all fleas which are in cell $ (i, j) $ after $ k-1 $ bells will jump away, none of them will be there anymore after $ k $ bells. Instead, all fleas from the (up to) 4 neighboring cells have a chance of entering cell $ (i,j) $.&lt;&#x2F;li&gt;
&lt;li&gt;Problems: this $ dp $ table doesn’t tell us anything about the number of fleas. A neighbor cell with 20 fleas has more chances of having some of them jump to the current cell than a neighbor with only 3 fleas. We don’t have enough information to compute an exact probability.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Maybe introduce another dimension:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;$ dp(i,j,x,k) = $ the probability of having exactly $ x $ fleas in cell $(i, j)$ after $k$ bells.&lt;&#x2F;li&gt;
&lt;li&gt;Initial state: $ dp(i, j, 1, 0) = 1 $. Every cell has exactly one flea in the beginning.&lt;&#x2F;li&gt;
&lt;li&gt;Recurrence: calculable but computationally expensive.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Assuming we want to compute the current state $ dp(i, j, x, k) $, what previous states could we have come from?&lt;&#x2F;p&gt;
&lt;p&gt;We know the fleas came from (up to) 4 neighbors. Those neighbors could have had any number of fleas themselves after $ k-1 $ bells, ranging from $0$ all the way to $900$. So the possible previous states are:&lt;&#x2F;p&gt;
&lt;p&gt;$$ dp(i_t, j_t, x_t, k-1), 1 \le t \le 4; 0 \le x_t \le 900 $$&lt;&#x2F;p&gt;
&lt;p&gt;Moreover, the $x$ fleas we have obtained in cell $(i,j)$ could have come in any combination from these neighbors. Essentially, we must try all configurations of $ x = \sum x_t’$, where $ 0 \le x_t’ \le x_t $.&lt;&#x2F;p&gt;
&lt;p&gt;With a bit more gymnastics we can compute the probability of having exactly $x_t’$ out of $x_t$ fleas jump in exactly the direction they need to in order to reach the current cell. The whole recurrence starts to take form but ends up looking extremely unwieldy. I will not attempt to write it here in full (or at all really).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;perspective-shift&quot;&gt;Perspective shift&lt;a class=&quot;zola-anchor&quot; href=&quot;#perspective-shift&quot; aria-label=&quot;Anchor link for: perspective-shift&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This unlocked the problem for me. What if, instead of tracking cells and the fleas contained within, we track the journey of individual fleas? This proves to be useful, despite adding a new dimension to the $dp$ table:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;$ dp(i, j, x, y, k) = $ the probability of the flea who started in cell $(i, j)$ to reach cell $(x,y)$ after exactly $k$ bells.&lt;&#x2F;li&gt;
&lt;li&gt;Initial state: $dp(i,j,i,j,0)=1$. Every flea has reached its own cell in the beginning.&lt;&#x2F;li&gt;
&lt;li&gt;Recurrence: the flea must have come from one of the (up to) 4 neighboring cells. Each neighbor $(x_t, y_t)$ has a probability of containing this particular flea after the previous bell (basically $ dp(i, j, x_t, y_t, k-1) $). In turn, the neighbor can have $ b_t $ neighbors of its own ($ 2 \le b_t \le 4 $). All of them are equally likely to be chosen as the jump destination but only one of them is our current cell. So we have a clear relation:&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;$$ dp(i, j, x, y, k) = \sum_{t=1}^4 \frac 1 b_t \cdot dp(i, j, x_t, y_t, k-1) $$&lt;&#x2F;p&gt;
&lt;p&gt;Of course, only valid neighbors are considered.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;putting-it-all-together&quot;&gt;Putting it all together&lt;a class=&quot;zola-anchor&quot; href=&quot;#putting-it-all-together&quot; aria-label=&quot;Anchor link for: putting-it-all-together&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Now we know for every flea how likely it is to end up in any cell of the grid after 50 bell rings. How is this useful?&lt;&#x2F;p&gt;
&lt;p&gt;We can treat cells individually. A cell $(x, y)$ will be unoccupied at the end only if &lt;em&gt;all&lt;&#x2F;em&gt; fleas land somewhere else. If we denote this probability as $p(x, y)$, then:&lt;&#x2F;p&gt;
&lt;p&gt;$$ p(x,y) = \prod (1-dp(i, j, x, y, k)) $$&lt;&#x2F;p&gt;
&lt;p&gt;As it turns out, this probability shows exactly by how much cell $(x, y)$ contributes to the expected number of unoccupied cells. The final answer is:&lt;&#x2F;p&gt;
&lt;p&gt;$$ E(X) = \sum p(x, y) $$&lt;&#x2F;p&gt;
&lt;p&gt;Complexity: $O(n^4 \cdot k)$. Execution time less than 2 seconds.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Project Euler #100: Arranged probability</title>
          <pubDate>Fri, 24 Sep 2021 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://sergiu.org/blog/euler-100/</link>
          <guid>https://sergiu.org/blog/euler-100/</guid>
          <description xml:base="https://sergiu.org/blog/euler-100/">&lt;blockquote&gt;
&lt;p&gt;If a box contains twenty-one coloured discs, composed of fifteen blue discs and six red discs, and two discs were taken at random, it can be seen that the probability of taking two blue discs, $P(BB) = \frac {15} {21} \times \frac {14} {20} = \frac 1 2$.&lt;&#x2F;p&gt;
&lt;p&gt;The next such arrangement, for which there is exactly 50% chance of taking two blue discs at random, is a box containing eighty-five blue discs and thirty-five red discs.&lt;&#x2F;p&gt;
&lt;p&gt;By finding the first arrangement to contain over $10^{12} = 1,000,000,000,000$ discs in total, determine the number of blue discs that the box would contain.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This is a fun problem that seems out of reach initially but can be reduced to something more simple.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;compute-the-probability&quot;&gt;Compute the probability&lt;a class=&quot;zola-anchor&quot; href=&quot;#compute-the-probability&quot; aria-label=&quot;Anchor link for: compute-the-probability&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Assuming there are $b$ blue discs and $r$ red discs, the probability of choosing one blue disc at random is $P_1 = \frac {b} {b+r}$. The probability of choosing another blue disc from the remaining set is $P_2 = \frac {b-1} {b+r-1}$.&lt;&#x2F;p&gt;
&lt;p&gt;So the probability of choosing 2 blue discs is $P(BB) = P_1 \cdot P_2 = \frac {b} {b+r} \cdot \frac {b-1} {b+r-1}$&lt;&#x2F;p&gt;
&lt;p&gt;We need to find the smallest solution of:&lt;&#x2F;p&gt;
&lt;p&gt;$$
\begin{cases}
\frac {b} {b+r} \cdot \frac {b-1} {b+r-1} = \frac 1 2 \newline
b + r &amp;gt; 10^{12}
\end{cases}
$$&lt;&#x2F;p&gt;
&lt;p&gt;If we consider $b$ to be a constant, the first equation can be rewritten to express $r$ as a function of $b$. In short:&lt;&#x2F;p&gt;
&lt;p&gt;$$ r^2  + (2b-1) \cdot r + (b-b^2) = 0 $$&lt;&#x2F;p&gt;
&lt;p&gt;Which has at most two natural roots:&lt;&#x2F;p&gt;
&lt;p&gt;$$ r_{1,2} = \frac {1 - 2b \pm \sqrt {(2b-1)^2 - 4(b-b^2)} } 2 $$&lt;&#x2F;p&gt;
&lt;p&gt;We can now compute the corresponding $r$ for every possible $b$, if it exists. Assuming that $b$ and $r$ are on the same order of magnitude, this approach should find the answer after ~$10^{12}$ iterations.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;finding-patterns&quot;&gt;Finding patterns&lt;a class=&quot;zola-anchor&quot; href=&quot;#finding-patterns&quot; aria-label=&quot;Anchor link for: finding-patterns&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The previous approach finds several solutions quickly:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: right&quot;&gt;$Total$&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;$Blue$&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;$Red$&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;$21$&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;$15$&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;$6$&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;$120$&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;$85$&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;$35$&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;$697$&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;$493$&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;$204$&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;$4060$&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;$2871$&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;$1189$&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;$23661$&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;$16731$&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;$6930$&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;$137904$&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;$97513$&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;$40391$&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;$803761$&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;$568345$&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;$235416$&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: right&quot;&gt;$4684660$&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;$3312555$&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;$1372105$&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;It turns out that $b$ follows a known sequence (&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;oeis.org&#x2F;A011900&quot;&gt;A011900&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;p&gt;$ a(n) = 6\cdot a(n-1) - a(n-2) - 2 $, with $ a(0) = 1 $ and $ a(1) = 3 $&lt;&#x2F;p&gt;
&lt;p&gt;Similarly, $r$ is a triangular number (&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;oeis.org&#x2F;A001109&quot;&gt;A001109&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;p&gt;$ a(n) = 6\cdot a(n-1) - a(n-2) $, with $ a(0) = 0 $ and $ a(1) = 1 $&lt;&#x2F;p&gt;
&lt;p&gt;It takes less than 20 iterations to find the first solution which exceeds $10^{12}$.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Project Euler #429: Sum of squares of unitary divisors</title>
          <pubDate>Thu, 23 Sep 2021 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://sergiu.org/blog/euler-429/</link>
          <guid>https://sergiu.org/blog/euler-429/</guid>
          <description xml:base="https://sergiu.org/blog/euler-429/">&lt;blockquote&gt;
&lt;p&gt;A unitary divisor $d$ of a number $n$ is a divisor of $n$ that has the property $gcd(d, \frac n d) = 1$.&lt;&#x2F;p&gt;
&lt;p&gt;The unitary divisors of $4! = 24$ are $1, 3, 8$ and $24$.&lt;&#x2F;p&gt;
&lt;p&gt;The sum of their squares is $12 + 32 + 82 + 242 = 650$.&lt;&#x2F;p&gt;
&lt;p&gt;Let $S(n)$ represent the sum of the squares of the unitary divisors of $n$. Thus $S(4!)=650$.&lt;&#x2F;p&gt;
&lt;p&gt;Find $S(100 000 000!) \mod 1 000 000 009$.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;For clarity, let’s denote $n=10^8$ and $N=n!=10^8!$&lt;&#x2F;p&gt;
&lt;h3 id=&quot;observation-1&quot;&gt;Observation #1&lt;a class=&quot;zola-anchor&quot; href=&quot;#observation-1&quot; aria-label=&quot;Anchor link for: observation-1&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;$N$ is huge. It has ~$750$ million digits. Computing it is out of the question.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;observation-2&quot;&gt;Observation #2&lt;a class=&quot;zola-anchor&quot; href=&quot;#observation-2&quot; aria-label=&quot;Anchor link for: observation-2&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;We are looking for coprime divisors of some integer $N$. This means they are not allowed to have any prime factors in common. Moreover, their product is $N$ so together they must share exactly all factors of $N$.&lt;&#x2F;p&gt;
&lt;p&gt;If $d$ and $\frac N d$ are two such divisors, and $N$ can be factorized as $\prod p_i^{a_i}$, then every $p_i^{a_i}$ must belong to either $d$ or $\frac N d$. It can not be subdivided as that would imply $gcd(d, \frac N d)$ is at least $p_i$.&lt;&#x2F;p&gt;
&lt;p&gt;$N$ contains every prime factor in the interval $[2, n]$. There are $\pi(n) = 5761455$ such primes (&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;oeis.org&#x2F;A000720&quot;&gt;A000720&lt;&#x2F;a&gt;). Each of them can belong to either $d$ or $\frac n d$ so we can generate $2^{5761455}$ such pairs of divisors. Again, not feasible.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;observation-3&quot;&gt;Observation #3&lt;a class=&quot;zola-anchor&quot; href=&quot;#observation-3&quot; aria-label=&quot;Anchor link for: observation-3&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The sum of $k$-th powers of &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Unitary_divisor&quot;&gt;unitary divisors&lt;&#x2F;a&gt; of $n$ is denoted by $\sigma^*_k(n)$. Wikipedia doesn’t help much but &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;web.archive.org&#x2F;web&#x2F;20210717050404&#x2F;http:&#x2F;&#x2F;mathworld.wolfram.com&#x2F;UnitaryDivisorFunction.html&quot;&gt;MathWorld&lt;&#x2F;a&gt; has a useful formula for generating this function:&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;
$\sigma^*_k(\prod p_i^{a_i}) = \prod (1+p_i^ {k \cdot a_i}) $
&lt;&#x2F;p&gt;
&lt;p&gt;Using this notation, the answer is $\sigma^*_2(N)$, which can be computed in $O(\pi(n))$ – completely reasonable.&lt;&#x2F;p&gt;
&lt;p&gt;So we need a few things:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;All primes up to $n$.&lt;&#x2F;li&gt;
&lt;li&gt;The factorization of $N$ using said primes. Since $N=n!$, we can compute the factorization of every integer up to $n$ and merge the results.&lt;&#x2F;li&gt;
&lt;li&gt;The computation of $\sigma^*_2(N)$ using said factorization.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;A final implementation detail: the intermediate results can become significantly large. It is important to compute them modulo $ 10^9+9 $. Since the exponents $a_i$ can get fairly large too (on the same order of magnitude as $n$), it doesn’t hurt to use &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Exponentiation_by_squaring&quot;&gt;fast exponentiation&lt;&#x2F;a&gt; too.&lt;&#x2F;p&gt;
&lt;p&gt;This solution runs in ~1.5min on my machine: 14s generating primes, 70s performing the factorization and &amp;lt;1s computing $\sigma^*_2(N)$.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Favorite CLI tools (and some GUIs too)</title>
          <pubDate>Wed, 17 Mar 2021 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://sergiu.org/blog/favorite-cli-tools/</link>
          <guid>https://sergiu.org/blog/favorite-cli-tools/</guid>
          <description xml:base="https://sergiu.org/blog/favorite-cli-tools/">&lt;p&gt;My first contact with Linux happened around 2008, back when Canonical was still distributing Ubuntu in the form of free CDs. The program was &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ubuntu.com&#x2F;blog&#x2F;shipit-comes-to-an-end&quot;&gt;discontinued&lt;&#x2F;a&gt; in 2011. And yes, my official copy of Ubuntu 10.04 LTS has been lost in time:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;sergiu.org&#x2F;blog&#x2F;favorite-cli-tools&#x2F;ubuntu-lineup.jpg&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I’ve accumulated many tools and scripts over the years. Some of them made my life easier, some ended up costing more time&lt;sup&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;1205&#x2F;&quot;&gt;[xkcd]&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; to implement or figure out than they saved in the long run. This is a collection of those that I got the most use out of.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;sergiu.org&#x2F;blog&#x2F;favorite-cli-tools&#x2F;kubuntu-cd-closeup.jpg&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;arandr&quot;&gt;ARandR&lt;a class=&quot;zola-anchor&quot; href=&quot;#arandr&quot; aria-label=&quot;Anchor link for: arandr&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;christian.amsuess.com&#x2F;tools&#x2F;arandr&#x2F;&quot;&gt;ARandR&lt;&#x2F;a&gt; is a GUI for &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;wiki.archlinux.org&#x2F;index.php&#x2F;Xrandr&quot;&gt;XRandR&lt;&#x2F;a&gt;, the monitor configuration utility for X. The latter provides powerful but inconvenient controls. For example, this is how I can set up my external monitor to extend on top of my laptop screen:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#f5f5f5;color:#1f1f1f;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; xrandr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt; --output&lt;&#x2F;span&gt;&lt;span&gt; eDP1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;  --mode&lt;&#x2F;span&gt;&lt;span&gt; 1920x1080&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt; --rotate&lt;&#x2F;span&gt;&lt;span&gt; normal&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt; --primary &lt;&#x2F;span&gt;&lt;span&gt;\
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;         --output&lt;&#x2F;span&gt;&lt;span&gt; HDMI1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt; --mode&lt;&#x2F;span&gt;&lt;span&gt; 2560x1440&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt; --rotate&lt;&#x2F;span&gt;&lt;span&gt; normal&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt; --above&lt;&#x2F;span&gt;&lt;span&gt; eDP1
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For any other non-trivial setup, the command gets messy. You might end up setting absolute positions (&lt;code&gt;--pos&lt;&#x2F;code&gt;), changing refresh rates (&lt;code&gt;--rate&lt;&#x2F;code&gt;) or writing your custom scripts depending on several setups you cycle between (laptop only &#x2F; home  &#x2F; office).&lt;&#x2F;p&gt;
&lt;p&gt;ARandR simplifies this by allowing graphical control. The same &lt;code&gt;xrandr&lt;&#x2F;code&gt; command from above is equivalent to the following layout. Except now you don’t have to remember any display names, supported resolutions or refresh rates.&lt;&#x2F;p&gt;
&lt;div align=&quot;center&quot;&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;sergiu.org&#x2F;blog&#x2F;favorite-cli-tools&#x2F;arandr.jpg&quot; alt=&quot;arandr&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;mons&quot;&gt;Mons&lt;a class=&quot;zola-anchor&quot; href=&quot;#mons&quot; aria-label=&quot;Anchor link for: mons&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Ventto&#x2F;mons&quot;&gt;Mons&lt;&#x2F;a&gt; is another monitor management tool. It also uses &lt;code&gt;xrandr&lt;&#x2F;code&gt; under the hood and exposes the most common use-cases as simple commands. This is especially useful when paired with a window manager which doesn’t handle monitor management natively.&lt;&#x2F;p&gt;
&lt;p&gt;The most common commands for me:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#f5f5f5;color:#1f1f1f;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; mons&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt; -o  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#7f8989;&quot;&gt;# use only primary display
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; mons&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt; -e&lt;&#x2F;span&gt;&lt;span&gt; (top,left,right,bottom)  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#7f8989;&quot;&gt;# extend the primary display on a particular side
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; mons&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt; -a  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#7f8989;&quot;&gt;# switch to a single display automatically if the external monitor is disconnected
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;exa&quot;&gt;exa&lt;a class=&quot;zola-anchor&quot; href=&quot;#exa&quot; aria-label=&quot;Anchor link for: exa&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;the.exa.website&#x2F;&quot;&gt;exa&lt;&#x2F;a&gt; is a &lt;em&gt;modern replacement for &lt;code&gt;ls&lt;&#x2F;code&gt;&lt;&#x2F;em&gt;. It’s fast, comes with better defaults (color output, human-readable sizes, etc) and expands on the features of &lt;code&gt;ls&lt;&#x2F;code&gt;. I’ve switched to it years ago: &lt;code&gt;alias ls &#x27;exa -lg&#x27;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Examples:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#f5f5f5;color:#1f1f1f;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; exa&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt; -s&lt;&#x2F;span&gt;&lt;span&gt; new    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#7f8989;&quot;&gt;# sort by newest
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; exa&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt; -T        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#7f8989;&quot;&gt;# show a tree
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; exa&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt; -l --git  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#7f8989;&quot;&gt;# show git information
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;taskwarrior&quot;&gt;Taskwarrior&lt;a class=&quot;zola-anchor&quot; href=&quot;#taskwarrior&quot; aria-label=&quot;Anchor link for: taskwarrior&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;taskwarrior.org&#x2F;&quot;&gt;Taskwarrior&lt;&#x2F;a&gt; is a CLI tool for managing your TODO list. It is often paired with the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Getting_Things_Done&quot;&gt;GTD methodology&lt;&#x2F;a&gt; which I’ve applied on and off for the past couple of years.&lt;&#x2F;p&gt;
&lt;p&gt;My usual workflow looks like this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#f5f5f5;color:#1f1f1f;&quot;&gt;&lt;code&gt;&lt;span&gt;$ task proj:work.ml add &amp;quot;write design doc&amp;quot; due:3d
&lt;&#x2F;span&gt;&lt;span&gt;Created task 64.
&lt;&#x2F;span&gt;&lt;span&gt;The project &amp;#39;work.ml&amp;#39; has changed.
&lt;&#x2F;span&gt;&lt;span&gt;Project &amp;#39;work.ml&amp;#39; is 91% complete (15 of 170 tasks remaining).
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;$ task annotate 64 &amp;quot;to be reviewed by X and Y&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;Annotating task 64 &amp;#39;write design doc&amp;#39;.
&lt;&#x2F;span&gt;&lt;span&gt;Annotated 1 task.
&lt;&#x2F;span&gt;&lt;span&gt;Project &amp;#39;work.ml&amp;#39; is 91% complete (15 of 170 tasks remaining).
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;$ task ls project:work.ml
&lt;&#x2F;span&gt;&lt;span&gt;ID D Project        Tags     Due  Description
&lt;&#x2F;span&gt;&lt;span&gt;64   work.ml                  2d  write design doc
&lt;&#x2F;span&gt;&lt;span&gt;                                    2021-03-14 to be reviewed by X and Y
&lt;&#x2F;span&gt;&lt;span&gt;25   work.ml        someday  1mo  enforce lowercase asset names
&lt;&#x2F;span&gt;&lt;span&gt;23   work.ml        2020Q4#3      add whackamole jobs to annealing
&lt;&#x2F;span&gt;&lt;span&gt;53   work.ml.router               create blade targets for main router
&lt;&#x2F;span&gt;&lt;span&gt;54 D work.ml        2020Q4#4 4mo  implement config watcher
&lt;&#x2F;span&gt;&lt;span&gt;55   work.ml        2020Q4#5 4mo  write one-pager about aliasing consistency
&lt;&#x2F;span&gt;&lt;span&gt;26   work.ml        obsolete      move partition into model metadata
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I have different projects depending on what I’m working on. I usually set rough deadlines and dependencies between tasks and collect any helpful data (links to bugs, code changes, documentation, &lt;em&gt;etc.&lt;&#x2F;em&gt;) as annotations. The brain behind Taskwarrior sorts existing tasks using a metric called &lt;strong&gt;urgency&lt;&#x2F;strong&gt;. For example, blocked tasks are less urgent than non-blocked ones. Tasks with upcoming deadlines are more urgent than tasks scheduled far into the future.&lt;&#x2F;p&gt;
&lt;p&gt;Once my work is added and classified properly, I go through &lt;code&gt;to&lt;&#x2F;code&gt; (overdue tasks) and &lt;code&gt;tt&lt;&#x2F;code&gt; (tasks which are due today):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#f5f5f5;color:#1f1f1f;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#b39f04;&quot;&gt;alias &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c23f31;&quot;&gt;t  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d07711;&quot;&gt;&amp;#39;task&amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b39f04;&quot;&gt;alias &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c23f31;&quot;&gt;ta &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d07711;&quot;&gt;&amp;#39;task active&amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b39f04;&quot;&gt;alias &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c23f31;&quot;&gt;tn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d07711;&quot;&gt;&amp;#39;task next&amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b39f04;&quot;&gt;alias &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c23f31;&quot;&gt;to &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d07711;&quot;&gt;&amp;#39;task overdue&amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b39f04;&quot;&gt;alias &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c23f31;&quot;&gt;ts &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d07711;&quot;&gt;&amp;#39;task sync&amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b39f04;&quot;&gt;alias &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c23f31;&quot;&gt;tt &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d07711;&quot;&gt;&amp;#39;task due:today&amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b39f04;&quot;&gt;alias &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c23f31;&quot;&gt;whatdididothisweek &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d07711;&quot;&gt;&amp;#39;task completed end.after:(date +%Y-%m-%d)-7d&amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b39f04;&quot;&gt;alias &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c23f31;&quot;&gt;whatdididotoday &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d07711;&quot;&gt;&amp;#39;task completed end.after:(date +%Y-%m-%d)&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Crossing an item off a list sometimes feels more rewarding than doing the actual work. I found this process helpful in keeping momentum when working on boring parts of my projects. It also helped when I was feeling a complete lack of progress. Instead of staying blocked, I could usually split my work into almost trivially-sized chunks and process them one at a time. The graphical reports are a nice bonus feature too:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;sergiu.org&#x2F;blog&#x2F;favorite-cli-tools&#x2F;taskwarrior-report.jpg&quot; alt=&quot;Taskwarrior Burndown Report&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;On top of this, Taskwarrior can be deployed as a server. I’ve done this in order to have data consistency between all my clients:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;personal laptop&lt;&#x2F;li&gt;
&lt;li&gt;work laptop&lt;&#x2F;li&gt;
&lt;li&gt;remote workstation&lt;&#x2F;li&gt;
&lt;li&gt;android phone (&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;play.google.com&#x2F;store&#x2F;apps&#x2F;details?id=kvj.taskw&amp;amp;hl=en&amp;amp;gl=US&quot;&gt;app&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;as well as daily backups on Google Drive.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;mosh&quot;&gt;Mosh&lt;a class=&quot;zola-anchor&quot; href=&quot;#mosh&quot; aria-label=&quot;Anchor link for: mosh&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This is one I’ve known about since highschool (thanks to &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ieval.ro&#x2F;cv.txt&quot;&gt;Marius&lt;&#x2F;a&gt;) but only got around to using very recently.&lt;&#x2F;p&gt;
&lt;p&gt;In short, &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;mosh.org&#x2F;&quot;&gt;mosh&lt;&#x2F;a&gt; is a replacement for SSH. From the surface, it looks and behaves extremely similarly. However, it has some &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;mosh.org&#x2F;mosh-paper.pdf&quot;&gt;smart features&lt;&#x2F;a&gt; which make it more resilient to intermittent connectivity.&lt;&#x2F;p&gt;
&lt;p&gt;The result is a remote connection which feels like a local terminal session. You can put your machine to sleep, come back to it a week later and resume instantly from where you left off.&lt;&#x2F;p&gt;
&lt;p&gt;Makes for a powerful workspace when combined with &lt;code&gt;tmux&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;alacritty&quot;&gt;Alacritty&lt;a class=&quot;zola-anchor&quot; href=&quot;#alacritty&quot; aria-label=&quot;Anchor link for: alacritty&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;My &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;alacritty&#x2F;alacritty&quot;&gt;terminal emulator of choice&lt;&#x2F;a&gt;. It’s implemented in Rust, it’s fast (GPU accelerated), easy to configure (YAML) and feels modern to use.&lt;&#x2F;p&gt;
&lt;p&gt;Some features such as scrolling or splitting tabs are excluded in the name of simplicity. While this can present a turn-off, I haven’t noticed any drawbacks since &lt;code&gt;tmux&lt;&#x2F;code&gt; has already been fulfilling these needs for me.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;spongebob&quot;&gt;Spongebob&lt;a class=&quot;zola-anchor&quot; href=&quot;#spongebob&quot; aria-label=&quot;Anchor link for: spongebob&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This is a &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;pastebin.com&#x2F;raw&#x2F;G8q5uT7r&quot;&gt;script&lt;&#x2F;a&gt; I wrote a while ago to aid me in using the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;knowyourmeme.com&#x2F;memes&#x2F;mocking-spongebob&quot;&gt;mocking Spongebob&lt;&#x2F;a&gt; meme. Doesn’t rank that high on the utility spectrum but it’s fun enough.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;❱ &lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;echo&lt;&#x2F;span&gt; &lt;span style=&quot;color:#005fd7;&quot;&gt;&quot;you can&#x27;t just automate yourself out of a job&quot; |&lt;&#x2F;span&gt; &lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;spongebob&lt;&#x2F;span&gt;
YoU CaN&#x27;T jUsT AuToMAte YoUrSeLf oUt Of A JoB
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;ss&quot;&gt;&lt;code&gt;ss&lt;&#x2F;code&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#ss&quot; aria-label=&quot;Anchor link for: ss&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Another &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;pastebin.com&#x2F;raw&#x2F;Y8AKRmPC&quot;&gt;script&lt;&#x2F;a&gt;. This one uses &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Scrot&quot;&gt;scrot&lt;&#x2F;a&gt; to take a screenshot of an area, save it to &lt;code&gt;~&#x2F;Pictures&lt;&#x2F;code&gt; and copy it to clipboard.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;switch-sink&quot;&gt;&lt;code&gt;switch_sink&lt;&#x2F;code&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#switch-sink&quot; aria-label=&quot;Anchor link for: switch-sink&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;pastebin.com&#x2F;raw&#x2F;1WKRrQ2m&quot;&gt;This one&lt;&#x2F;a&gt; comes in handy when there are multiple audio outputs (sinks) configured in &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;wiki.archlinux.org&#x2F;index.php&#x2F;PulseAudio&quot;&gt;PulseAudio&lt;&#x2F;a&gt;. For example, as shown in &lt;code&gt;pavucontrol&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;div align=&quot;center&quot;&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;sergiu.org&#x2F;blog&#x2F;favorite-cli-tools&#x2F;pavucontrol.jpg&quot; alt=&quot;pavucontrol&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;code&gt;switch_sink&lt;&#x2F;code&gt; picks a random sink, sets it as default and moves all active streams to it. On my machine, it’s mapped to the &lt;a href=&quot;https:&#x2F;&#x2F;sergiu.org&#x2F;blog&#x2F;favorite-cli-tools&#x2F;xf86tools.jpg&quot;&gt;&lt;code&gt;XF86Tools&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; key. This lets me cycle all audio between the built-in laptop speakers, my external audio monitors and my bluetooth headphones at the press of a button.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;dslr-webcam-sh&quot;&gt;&lt;code&gt;dslr_webcam.sh&lt;&#x2F;code&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#dslr-webcam-sh&quot; aria-label=&quot;Anchor link for: dslr-webcam-sh&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;For the past year I’ve been using my friend’s DSLR camera as a webcam for video calls. I found a solution in the form of &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;www.gphoto.org&#x2F;&quot;&gt;gphoto2&lt;&#x2F;a&gt; which can create a &lt;em&gt;virtual video device&lt;&#x2F;em&gt;, also known as a V4L2 loopback device. The &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;pastebin.com&#x2F;raw&#x2F;gh60Pm64&quot;&gt;script&lt;&#x2F;a&gt; uses &lt;code&gt;gphoto2&lt;&#x2F;code&gt; and &lt;code&gt;ffmpeg&lt;&#x2F;code&gt; to encode the stream.&lt;&#x2F;p&gt;
&lt;p&gt;The camera I’m using has an old (maybe proprietary?) connector and is very limited in terms of bandwidth. As such, it can only go up to ~480p 24fps. Still, the picture quality is much better and I can make use of my camera tripod and lenses. On top of this, I don’t have to open my laptop in order to use the built-in webcam.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;xclip&quot;&gt;&lt;code&gt;xclip&lt;&#x2F;code&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#xclip&quot; aria-label=&quot;Anchor link for: xclip&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;linux.die.net&#x2F;man&#x2F;1&#x2F;xclip&quot;&gt;xclip&lt;&#x2F;a&gt; is a command line interface to X selections (clipboard). I use it for copying the output of certain commands to my clipboard. For example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#f5f5f5;color:#1f1f1f;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; cat &#x2F;etc&#x2F;hosts &lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;xclip -selection&lt;&#x2F;span&gt;&lt;span&gt; clipboard
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It also works with images (see &lt;a href=&quot;#ss&quot;&gt;&lt;code&gt;ss&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;watch&quot;&gt;&lt;code&gt;watch&lt;&#x2F;code&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#watch&quot; aria-label=&quot;Anchor link for: watch&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;linux.die.net&#x2F;man&#x2F;1&#x2F;watch&quot;&gt;watch&lt;&#x2F;a&gt; repeats a command every N seconds and updates the output in-place.&lt;&#x2F;p&gt;
&lt;p&gt;For example, monitoring CPU temperature:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#f5f5f5;color:#1f1f1f;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; watch&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt; -n&lt;&#x2F;span&gt;&lt;span&gt; 1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d07711;&quot;&gt;&amp;#39;sensors | grep &amp;quot;Core&amp;quot;&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#f5f5f5;color:#1f1f1f;&quot;&gt;&lt;code&gt;&lt;span&gt;Every 1.0s: sensors | grep &amp;quot;Core&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;Core 0:        +44.0°C  (high = +100.0°C, crit = +100.0°C)
&lt;&#x2F;span&gt;&lt;span&gt;Core 1:        +45.0°C  (high = +100.0°C, crit = +100.0°C)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;ranger&quot;&gt;Ranger&lt;a class=&quot;zola-anchor&quot; href=&quot;#ranger&quot; aria-label=&quot;Anchor link for: ranger&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ranger&#x2F;ranger&quot;&gt;Ranger&lt;&#x2F;a&gt; is a text-based file explorer based on curses. It has been an essential tool for navigating and exploring remote machines.&lt;&#x2F;p&gt;
&lt;p&gt;One of the most common non-trivial use cases is cleaning up large files. Ranger’s vi keybindings make this easy: &lt;code&gt;vdcv&lt;&#x2F;code&gt; (in&lt;strong&gt;v&lt;&#x2F;strong&gt;ert selection, &lt;strong&gt;d&lt;&#x2F;strong&gt;isplay &lt;strong&gt;c&lt;&#x2F;strong&gt;ummulative sizes, in&lt;strong&gt;v&lt;&#x2F;strong&gt;ert again), followed by &lt;code&gt;os&lt;&#x2F;code&gt; (&lt;strong&gt;o&lt;&#x2F;strong&gt;rder by &lt;strong&gt;s&lt;&#x2F;strong&gt;ize). Then go through the results, &lt;code&gt;Space&lt;&#x2F;code&gt; to select and &lt;code&gt;:delete&lt;&#x2F;code&gt; as needed.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;As with most things, I’ve barely scratched the surface of what some of these tools are capable of. My usual strategy relies on (1) discovering features organically, as needed and (2) occasionally doing a quick refresh of a particular tool. Most of the time this is as simple as scanning the docs or man page to see that else the tool can do. Sometimes it’s a more systematic approach, for example picking a random chapter of &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.oreilly.com&#x2F;library&#x2F;view&#x2F;practical-vim-2nd&#x2F;9781680501629&#x2F;&quot;&gt;Practical Vim&lt;&#x2F;a&gt; and using that as a way to fill knowledge gaps.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Preserving Terminal Colors On The Web</title>
          <pubDate>Sat, 27 Feb 2021 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://sergiu.org/blog/preserving-terminal-colors-on-the-web/</link>
          <guid>https://sergiu.org/blog/preserving-terminal-colors-on-the-web/</guid>
          <description xml:base="https://sergiu.org/blog/preserving-terminal-colors-on-the-web/">&lt;p&gt;There are a few different ways of adding code blocks to text-based web content, such as this blog post. I wanted to explore the available options in hope of finding a method that lets me preserve colors exactly as they are in the original text.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;markdown&quot;&gt;Markdown&lt;a class=&quot;zola-anchor&quot; href=&quot;#markdown&quot; aria-label=&quot;Anchor link for: markdown&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This post is mostly written in markdown. The built-in construct for a fenced code block (triple backticks) allows setting a language for syntax highlighting. For example:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;```rust
pub fn is_drive_document(&amp;self) -&gt; bool {
    self.drive_file
        .as_ref()
        .and_then(|f| f.mime_type.clone())
        .map(|t| EXTENSIONS.contains_key::&lt;str&gt;(&amp;t))
        == Some(true)
}
```
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which renders as:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#f5f5f5;color:#1f1f1f;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#668f14;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c23f31;&quot;&gt;is_drive_document&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#668f14;&quot;&gt;bool &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.drive_file
&lt;&#x2F;span&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b39f04;&quot;&gt;as_ref&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b39f04;&quot;&gt;and_then&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;| f.mime_type.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b39f04;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;())
&lt;&#x2F;span&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b39f04;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;t&lt;&#x2F;span&gt;&lt;span&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b3933a;&quot;&gt;EXTENSIONS&lt;&#x2F;span&gt;&lt;span&gt;.contains_key::&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#668f14;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;t))
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a2a001;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b3933a;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The actual list of supported languages depends on the syntax highlighting engine. Zola supports &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;documentation&#x2F;content&#x2F;syntax-highlighting&#x2F;&quot;&gt;over 100&lt;&#x2F;a&gt; languages. GitHub uses &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;github&#x2F;linguist&quot;&gt;linguist&lt;&#x2F;a&gt; which has &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;github&#x2F;linguist&#x2F;blob&#x2F;master&#x2F;lib&#x2F;linguist&#x2F;languages.yml&quot;&gt;over 500&lt;&#x2F;a&gt; language definitions.&lt;&#x2F;p&gt;
&lt;p&gt;This works fantastically well when writing code blocks in any of these predefined languages. The drawbacks are few and fairly minor: edge cases such as incorrect highlighting when using newer features of some languages or having custom prompts&#x2F;commands when writing console snippets.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;html-javascript&quot;&gt;HTML + JavaScript&lt;a class=&quot;zola-anchor&quot; href=&quot;#html-javascript&quot; aria-label=&quot;Anchor link for: html-javascript&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;There are many libraries for highlighting code on the web. The usual workflow involves:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Linking in a CSS and JS file, either locally or using a CDN.&lt;&#x2F;li&gt;
&lt;li&gt;Including a short script which triggers the highlighting logic.&lt;&#x2F;li&gt;
&lt;li&gt;Marking the HTML code elements with a certain class such that the highlighting library can identify them.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;One such library is &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;highlightjs.org&quot;&gt;highlight.js&lt;&#x2F;a&gt;. I included it in this page using a CDN and triggered the highlighter with a custom script. Since I’m not using highlight.js everywhere, I want to be able to enable it explicitly on certain elements.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;html&quot; style=&quot;background-color:#f5f5f5;color:#1f1f1f;&quot; class=&quot;language-html &quot;&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span style=&quot;color:#7f902a;&quot;&gt;&amp;lt;link rel=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d07711;&quot;&gt;&amp;quot;stylesheet&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#7f902a;&quot;&gt;href=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d07711;&quot;&gt;&amp;quot;&#x2F;&#x2F;cdnjs.cloudflare.com&#x2F;ajax&#x2F;libs&#x2F;highlight.js&#x2F;10.5.0&#x2F;styles&#x2F;default.min.css&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#7f902a;&quot;&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6486ab;&quot;&gt;&amp;lt;script src=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d07711;&quot;&gt;&amp;quot;&#x2F;&#x2F;cdnjs.cloudflare.com&#x2F;ajax&#x2F;libs&#x2F;highlight.js&#x2F;10.5.0&#x2F;highlight.min.js&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6486ab;&quot;&gt;&amp;gt;&amp;lt;&#x2F;script&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#f5f5f5;color:#1f1f1f;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;color:#7f8989;&quot;&gt;&#x2F;&#x2F; Only after the page has loaded.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a2a001;&quot;&gt;document&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b39f04;&quot;&gt;addEventListener&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d07711;&quot;&gt;&amp;quot;DOMContentLoaded&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#668f14;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#7f8989;&quot;&gt;&#x2F;&#x2F; Highlight all &amp;lt;code class=&amp;quot;highlightjs&amp;quot;&amp;gt; elements
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a2a001;&quot;&gt;document&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b39f04;&quot;&gt;querySelectorAll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d07711;&quot;&gt;&amp;#39;code.highlightjs&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b39f04;&quot;&gt;forEach&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;block &lt;&#x2F;span&gt;&lt;span style=&quot;color:#668f14;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;hljs&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c23f31;&quot;&gt;highlightBlock&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;block&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;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The same Rust snippet can then be included like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#f5f5f5;color:#1f1f1f;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;pre&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;code class&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d07711;&quot;&gt;&amp;quot;highlightjs&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; class&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d07711;&quot;&gt;&amp;quot;rust&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#7f8989;&quot;&gt;&#x2F;&#x2F; [...]
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;code&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;pre&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which results in:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background:#f0f0f0;&quot;&gt;&lt;code class=&quot;highlightjs&quot; class=&quot;rust&quot;&gt;pub fn is_drive_document(&amp;self) -&gt; bool {
    self.drive_file
        .as_ref()
        .and_then(|f| f.mime_type.clone())
        .map(|t| EXTENSIONS.contains_key::&lt;str&gt;(&amp;t))
        == Some(true)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;One advantage of this approach is the ability of customizing the library. You can choose to include only the languages that you care about. This reduces the payload and can make your web page load faster (compared to linking the complete library) as a result.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;sergiu.org&#x2F;blog&#x2F;preserving-terminal-colors-on-the-web&#x2F;highlightjs-custom-package.jpg&quot; alt=&quot;highlightjs custom package&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Changing the colorscheme also becomes trivial. Just pick a different CSS from the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;highlightjs&#x2F;highlight.js&#x2F;tree&#x2F;master&#x2F;src&#x2F;styles&quot;&gt;available styles&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If highlight.js falls short in some way, there are many other alternatives to experiment with:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;shjs.sourceforge.net&quot;&gt;SHJS&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;craig.is&#x2F;making&#x2F;rainbows&quot;&gt;Rainbow&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;prismjs.com&quot;&gt;Prism&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;asvd&#x2F;microlight&quot;&gt;microlight.js&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;EnlighterJS&#x2F;EnlighterJS&quot;&gt;EnlighterJS&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;ansi-escapes&quot;&gt;ANSI escapes&lt;a class=&quot;zola-anchor&quot; href=&quot;#ansi-escapes&quot; aria-label=&quot;Anchor link for: ansi-escapes&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Previous solutions rely on the assumption that the highlightable content is written in a recognized, well-defined language and does not contain errors. This is not always true. In the past, I found myself in situations where I wanted to capture the output of a terminal session without losing any color information. It is possible to programmatically highlight &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;github&#x2F;linguist&#x2F;blob&#x2F;b2834449f1dd9dd9b76652092bad9fc593f687d3&#x2F;lib&#x2F;linguist&#x2F;languages.yml#L5314&quot;&gt;console sessions&lt;&#x2F;a&gt; but it fails more often than not. This is increasingly problematic since many CLI tools benefit from color output nowadays. In most cases, colors increase readability and improve the user experience.&lt;&#x2F;p&gt;
&lt;p&gt;But there are many different tools which use colors and the output can be virtually anything. No predefined structure which lends itself to easy color matching.&lt;&#x2F;p&gt;
&lt;p&gt;In this case, you have to dig one layer deeper and access the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;ANSI_escape_code&quot;&gt;ANSI escape codes&lt;&#x2F;a&gt;. These are binary sequences embedded into text which dictate how it should be displayed in terms of color, styling and other variables. The name comes from the first character in such a code which is usually an ASCII escape character. ANSI codes are used extensively by terminal emulators.&lt;&#x2F;p&gt;
&lt;p&gt;However, they are for the most part not human readable. For example, the following mess converts into a nicely colored sentence:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#f5f5f5;color:#1f1f1f;&quot;&gt;&lt;code&gt;&lt;span&gt;^[[1;34mthis ^[[33mis ^[[31mcolored^[[32m text
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre&gt;
&lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;this &lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:olive;&quot;&gt;is &lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:red;&quot;&gt;colored&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:green;&quot;&gt; text
&lt;&#x2F;span&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In order to get this working, two things must be done:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;capturing-ansi-information&quot;&gt;Capturing ANSI information&lt;a class=&quot;zola-anchor&quot; href=&quot;#capturing-ansi-information&quot; aria-label=&quot;Anchor link for: capturing-ansi-information&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Copying and pasting colored text from a terminal emulator will most likely lose any color information. Redirecting all output to a file will likely do the same. This can be explained by an excerpt taken from the &lt;code&gt;ls&lt;&#x2F;code&gt; &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man1&#x2F;ls.1.html&quot;&gt;manpage&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre&gt;Using  color  to distinguish file types is disabled both by default and
with &lt;b&gt;--color&lt;&#x2F;b&gt;=&lt;i&gt;never&lt;&#x2F;i&gt;.  With &lt;b&gt;--color&lt;&#x2F;b&gt;=&lt;i&gt;auto&lt;&#x2F;i&gt;, ls emits color codes only  when
standard  output is connected to a terminal.  The &lt;b&gt;LS_COLORS&lt;&#x2F;b&gt; environment
variable can change the settings.  Use the dircolors command to set it.&lt;&#x2F;pre&gt;
&lt;p&gt;One workaround is to set &lt;code&gt;--color=always&lt;&#x2F;code&gt; and redirect the output to a file. Of course, this solution only works for commands which have such a flag. It also gets messy when working with interactive programs, since it essentially separates away all user input. Instead of having a single interactive session, you end up with a blank terminal used only for input and another one for &lt;code&gt;tail&lt;&#x2F;code&gt;-ing the output file. Not a great experience.&lt;&#x2F;p&gt;
&lt;p&gt;Luckily, we have &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man1&#x2F;script.1.html&quot;&gt;script&lt;&#x2F;a&gt;. This tool creates a log of a terminal session and saves it to disk:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#f5f5f5;color:#1f1f1f;&quot;&gt;&lt;code&gt;&lt;span&gt;~ ❱ script
&lt;&#x2F;span&gt;&lt;span&gt;Script started, output log file is &amp;#39;typescript&amp;#39;.
&lt;&#x2F;span&gt;&lt;span&gt;~ ❱ exa -l &#x2F;srv
&lt;&#x2F;span&gt;&lt;span&gt;dr-xr-xr-x - root   19 Jan  2:32 ftp
&lt;&#x2F;span&gt;&lt;span&gt;drwxrwxr-x - sergiu 20 Feb 14:25 ghost
&lt;&#x2F;span&gt;&lt;span&gt;drwxr-xr-x - sergiu 17 Feb 12:47 sergiu.org
&lt;&#x2F;span&gt;&lt;span&gt;drwxr-xr-x - root   19 Jan  2:32 http
&lt;&#x2F;span&gt;&lt;span&gt;drwxr-xr-x - http   10 Feb 14:57 manythanks
&lt;&#x2F;span&gt;&lt;span&gt;~ ❱ exit
&lt;&#x2F;span&gt;&lt;span&gt;Script done.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The result is a binary file which will show exactly the same terminal information when &lt;code&gt;cat&lt;&#x2F;code&gt;. For what it’s worth, here’s what a &lt;a href=&quot;https:&#x2F;&#x2F;sergiu.org&#x2F;blog&#x2F;preserving-terminal-colors-on-the-web&#x2F;typescript-hexdump.html&quot;&gt;hexdump&lt;&#x2F;a&gt; of it looks like.&lt;&#x2F;p&gt;
&lt;p&gt;Fun fact: if &lt;code&gt;script&lt;&#x2F;code&gt; is executed with timing information (&lt;code&gt;-T, --log-timing file&lt;&#x2F;code&gt;) it can be replayed at a later time using &lt;code&gt;script-replay&lt;&#x2F;code&gt;. This essentially simulates your shell interaction in real time.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;converting-ansi-to-html&quot;&gt;Converting ANSI to HTML&lt;a class=&quot;zola-anchor&quot; href=&quot;#converting-ansi-to-html&quot; aria-label=&quot;Anchor link for: converting-ansi-to-html&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The captured logfile is not useful on its own. It needs to be converted to HTML tags which convey the same information in a human readable form. I found a few tools for doing this. The ones I tried are &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pycontribs&#x2F;ansi2html&quot;&gt;ansi2html&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;theZiz&#x2F;aha&quot;&gt;aha&lt;&#x2F;a&gt;. In my limited testing, &lt;code&gt;aha&lt;&#x2F;code&gt; provided better results and required less cleanup overall so I’m going to use it to illustrate this step.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#f5f5f5;color:#1f1f1f;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; aha&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt; -f&lt;&#x2F;span&gt;&lt;span&gt; typescript&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt; --no-header &lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; render.html
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The generated HTML is included below and looks much better than plaintext:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;~&lt;&#x2F;span&gt; ❱ &lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;exa&lt;&#x2F;span&gt; &lt;span style=&quot;color:#005fd7;&quot;&gt;-l &#x2F;srv&lt;&#x2F;span&gt;
&lt;span style=&quot;color:dimgray;&quot;&gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:dimgray;&quot;&gt;&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:olive;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#808080;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:green;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color:olive;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#808080;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:green;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color:olive;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#808080;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:green;&quot;&gt;x&lt;&#x2F;span&gt; &lt;span style=&quot;color:#808080;&quot;&gt;-&lt;&#x2F;span&gt; root   &lt;span style=&quot;color:blue;&quot;&gt;19 Jan  2:32&lt;&#x2F;span&gt; &lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;ftp&lt;&#x2F;span&gt;
&lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:olive;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:red;&quot;&gt;w&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:green;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color:olive;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:red;&quot;&gt;w&lt;&#x2F;span&gt;&lt;span style=&quot;color:green;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color:olive;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#808080;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:green;&quot;&gt;x&lt;&#x2F;span&gt; &lt;span style=&quot;color:#808080;&quot;&gt;-&lt;&#x2F;span&gt; &lt;span style=&quot;font-weight:bold;color:olive;&quot;&gt;sergiu&lt;&#x2F;span&gt; &lt;span style=&quot;color:blue;&quot;&gt;20 Feb 14:25&lt;&#x2F;span&gt; &lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;ghost&lt;&#x2F;span&gt;
&lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:olive;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:red;&quot;&gt;w&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:green;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color:olive;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#808080;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:green;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color:olive;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#808080;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:green;&quot;&gt;x&lt;&#x2F;span&gt; &lt;span style=&quot;color:#808080;&quot;&gt;-&lt;&#x2F;span&gt; &lt;span style=&quot;font-weight:bold;color:olive;&quot;&gt;sergiu&lt;&#x2F;span&gt; &lt;span style=&quot;color:blue;&quot;&gt;17 Feb 12:47&lt;&#x2F;span&gt; &lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;sergiu.org&lt;&#x2F;span&gt;
&lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:olive;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:red;&quot;&gt;w&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:green;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color:olive;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#808080;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:green;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color:olive;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#808080;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:green;&quot;&gt;x&lt;&#x2F;span&gt; &lt;span style=&quot;color:#808080;&quot;&gt;-&lt;&#x2F;span&gt; root   &lt;span style=&quot;color:blue;&quot;&gt;19 Jan  2:32&lt;&#x2F;span&gt; &lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;http&lt;&#x2F;span&gt;
&lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:olive;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:red;&quot;&gt;w&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:green;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color:olive;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#808080;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:green;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color:olive;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#808080;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:green;&quot;&gt;x&lt;&#x2F;span&gt; &lt;span style=&quot;color:#808080;&quot;&gt;-&lt;&#x2F;span&gt; http   &lt;span style=&quot;color:blue;&quot;&gt;10 Feb 14:57&lt;&#x2F;span&gt; &lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;manythanks&lt;&#x2F;span&gt;
&lt;span style=&quot;font-weight:bold;&quot;&gt;~&lt;&#x2F;span&gt; ❱ &lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;exit&lt;&#x2F;span&gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The tool is not perfect. In my personal setup, I use the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;fishshell.com&quot;&gt;fish&lt;&#x2F;a&gt; shell with many autocomplete plugins. Some of them output ANSII escape codes in real time as I’m typing. This messes up the log file so I have to manually go in and do some cleanup afterwards. Most of it boils down to carriage returns (&lt;code&gt;^M&lt;&#x2F;code&gt;) and other unparsed garbage (special characters, partial autocomplete snippets, etc). I’ve tried the same exercise on bash with a blank &lt;code&gt;.bashrc&lt;&#x2F;code&gt; and had much better results. There’s certainly room for improvement and refinements to be done.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;For the most part, I think the simple Markdown code blocks work best. But for anything terminal-related I would like to find a better workflow around ANSI codes and tools like &lt;code&gt;aha&lt;&#x2F;code&gt;. Either fix the bad interaction with fish (possibly by turning off autocomplete suggestions temporarily) or maybe switch to bash altogether when recording terminal interaction snippets.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Building This Blog With Zola</title>
          <pubDate>Wed, 10 Feb 2021 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://sergiu.org/blog/building-this-blog-with-zola/</link>
          <guid>https://sergiu.org/blog/building-this-blog-with-zola/</guid>
          <description xml:base="https://sergiu.org/blog/building-this-blog-with-zola/">&lt;p&gt;While looking for options of reviving my old blog, I initially wanted to use the same platform as before – &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ghost.org&#x2F;&quot;&gt;Ghost&lt;&#x2F;a&gt;. After assessing the state of Ghost on Arch, I decided it’s probably not worth the effort so I did some research on &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;news.ycombinator.com&#x2F;&quot;&gt;HN&lt;&#x2F;a&gt;. Some solutions came up repeatedly:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;bearblog.dev&quot;&gt;Bear&lt;&#x2F;a&gt; – this would have been my first choice but it does not currently support self hosting.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;micro.blog&#x2F;&quot;&gt;Micro.blog&lt;&#x2F;a&gt; – I want a free solution, especially as I am hosting it on my own server.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;blot.im&#x2F;&quot;&gt;Blot&lt;&#x2F;a&gt; – same.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;&quot;&gt;Medium&lt;&#x2F;a&gt; – there are no words for how much I hate paywalls and gated content. It’s also one of the reasons I stopped reading &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;quora.com&quot;&gt;Quora&lt;&#x2F;a&gt; years ago. If your website is going to ask me to (1) disable my adbocker, (2) create a “free” account or (3) sign up for a paid subscription, I will just close it and move on with my life.
&lt;img src=&quot;https:&#x2F;&#x2F;sergiu.org&#x2F;blog&#x2F;building-this-blog-with-zola&#x2F;medium-login-wall.png&quot; alt=&quot;medium-login-wall&quot; &#x2F;&gt;
On the same note, I have some resistance towards the whole concept of a centralized Internet. I don’t like big social networks. The Internet was more fun when it consisted of a bunch of personal websites that people hosted themselves. If this resonates with you, it’s also worth reading about &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;indieweb.org&#x2F;POSSE&quot;&gt;POSSE&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I eventually landed on &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;&quot;&gt;Zola&lt;&#x2F;a&gt;, which I used to generate this website. I chose this engine for a few reasons:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;it generates a simple site. I don’t like complex&#x2F;over-engineered services and bloated websites. I want a clean and simple landing page which is easy to navigate. This website is mostly a collection of Markdown files with some CSS thrown on top.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;it’s implemented in Rust. I like Rust and have become familiar with it. As such, some concepts already come across more naturally. For example, Zola’s config is written in &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;documentation&#x2F;getting-started&#x2F;configuration&#x2F;&quot;&gt;toml&lt;&#x2F;a&gt; which is already the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;cargo&#x2F;reference&#x2F;manifest.html&quot;&gt;de-facto standard&lt;&#x2F;a&gt; for Rust.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;it’s easy to set up. The &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;aur.archlinux.org&#x2F;&quot;&gt;Arch User Repository&lt;&#x2F;a&gt; already includes &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;archlinux.org&#x2F;packages&#x2F;community&#x2F;x86_64&#x2F;zola&#x2F;&quot;&gt;zola&lt;&#x2F;a&gt; as a community package.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;it’s a simple tool. To emphasize this point, just take a look at what the arch package contains:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;~&lt;&#x2F;span&gt; ❱ &lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;trizen&lt;&#x2F;span&gt; &lt;span style=&quot;color:#005fd7;&quot;&gt;-Ql zola&lt;&#x2F;span&gt;
&lt;span style=&quot;font-weight:bold;&quot;&gt;zola&lt;&#x2F;span&gt; &#x2F;usr&#x2F;
&lt;span style=&quot;font-weight:bold;&quot;&gt;zola&lt;&#x2F;span&gt; &#x2F;usr&#x2F;bin&#x2F;
&lt;span style=&quot;font-weight:bold;&quot;&gt;zola&lt;&#x2F;span&gt; &#x2F;usr&#x2F;bin&#x2F;zola
&lt;span style=&quot;font-weight:bold;&quot;&gt;zola&lt;&#x2F;span&gt; &#x2F;usr&#x2F;share&#x2F;
&lt;span style=&quot;font-weight:bold;&quot;&gt;zola&lt;&#x2F;span&gt; &#x2F;usr&#x2F;share&#x2F;licenses&#x2F;
&lt;span style=&quot;font-weight:bold;&quot;&gt;zola&lt;&#x2F;span&gt; &#x2F;usr&#x2F;share&#x2F;licenses&#x2F;zola&#x2F;
&lt;span style=&quot;font-weight:bold;&quot;&gt;zola&lt;&#x2F;span&gt; &#x2F;usr&#x2F;share&#x2F;licenses&#x2F;zola&#x2F;LICENSE
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Just one binary and a LICENSE file. That’s it.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;it has a built-in web server for local development. Although I now use &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.nginx.com&#x2F;&quot;&gt;nginx&lt;&#x2F;a&gt; to serve the static files, this was extremely useful in the beginning for just trying stuff out.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;setup-and-initial-configuration&quot;&gt;Setup and initial configuration&lt;a class=&quot;zola-anchor&quot; href=&quot;#setup-and-initial-configuration&quot; aria-label=&quot;Anchor link for: setup-and-initial-configuration&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Installing Zola on Arch is straightforward. &lt;em&gt;Note:&lt;&#x2F;em&gt; I use &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;trizen&#x2F;trizen&quot;&gt;trizen&lt;&#x2F;a&gt; instead of &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;wiki.archlinux.org&#x2F;index.php&#x2F;pacman&quot;&gt;pacman&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;~&lt;&#x2F;span&gt; ❱ &lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;trizen&lt;&#x2F;span&gt; &lt;span style=&quot;color:#005fd7;&quot;&gt;-S zola&lt;&#x2F;span&gt;
&lt;span style=&quot;font-weight:bold;&quot;&gt;&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;::&lt;&#x2F;span&gt; &lt;span style=&quot;font-weight:bold;&quot;&gt;Pacman command: &lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;sudo &#x2F;usr&#x2F;bin&#x2F;pacman -S&lt;&#x2F;span&gt;
resolving dependencies...
looking for conflicting packages...

&lt;span style=&quot;font-weight:bold;&quot;&gt;Packages (1)&lt;&#x2F;span&gt; zola-0.13.0-1

&lt;span style=&quot;font-weight:bold;&quot;&gt;Total Download Size: &lt;&#x2F;span&gt;   5.91 MiB
&lt;span style=&quot;font-weight:bold;&quot;&gt;Total Installed Size:&lt;&#x2F;span&gt;  20.14 MiB

&lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt; Proceed with installation? [Y&#x2F;n] &lt;&#x2F;span&gt;y
&lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt; Retrieving packages...&lt;&#x2F;span&gt;
 zola-0.13.0-1-x86_64           5.9 MiB  4.11 MiB&#x2F;s 00:01 [#############################] 100%
(1&#x2F;1) checking keys in keyring                            [#############################] 100%
(1&#x2F;1) checking package integrity                          [#############################] 100%
(1&#x2F;1) loading package files                               [#############################] 100%
(1&#x2F;1) checking for file conflicts                         [#############################] 100%
(1&#x2F;1) checking available disk space                       [#############################] 100%
&lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt; Processing package changes...
&lt;&#x2F;span&gt;(1&#x2F;1) installing zola                                     [#############################] 100%
&lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt; Running post-transaction hooks...
&lt;&#x2F;span&gt;(1&#x2F;1) Arming ConditionNeedsUpdate...
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;zola&lt;&#x2F;code&gt; binary exposes the &lt;code&gt;init&lt;&#x2F;code&gt; command for initializing a blank website. I decided to create mine under &lt;code&gt;&#x2F;srv&#x2F;sergiu.org&lt;&#x2F;code&gt; alongside some of the other web services I host:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;~&lt;&#x2F;span&gt; ❱ &lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;sudo&lt;&#x2F;span&gt; &lt;span style=&quot;color:#005fd7;&quot;&gt;mkdir &#x2F;srv&#x2F;sergiu.org&lt;&#x2F;span&gt;
&lt;span style=&quot;font-weight:bold;&quot;&gt;~&lt;&#x2F;span&gt; ❱ &lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;sudo&lt;&#x2F;span&gt; &lt;span style=&quot;color:#005fd7;&quot;&gt;chown sergiu:users &#x2F;srv&#x2F;sergiu.org&lt;&#x2F;span&gt;
&lt;span style=&quot;font-weight:bold;&quot;&gt;~&lt;&#x2F;span&gt; ❱ &lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;cd&lt;&#x2F;span&gt; &lt;span style=&quot;color:#005fd7;&quot;&gt;&#x2F;srv&lt;&#x2F;span&gt;
&#x2F;&lt;span style=&quot;font-weight:bold;&quot;&gt;srv&lt;&#x2F;span&gt; ❱ &lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;zola&lt;&#x2F;span&gt; &lt;span style=&quot;color:#005fd7;&quot;&gt;init sergiu.org&lt;&#x2F;span&gt;
&lt;span style=&quot;font-weight:bold;&quot;&gt;Welcome to Zola!&lt;&#x2F;span&gt;
&lt;span style=&quot;font-weight:bold;&quot;&gt;Please answer a few questions to get started quickly.&lt;&#x2F;span&gt;
&lt;span style=&quot;font-weight:bold;&quot;&gt;Any choices made can be changed by modifying the `config.toml` file later.&lt;&#x2F;span&gt;
&amp;gt; What is the URL of your site? (https:&#x2F;&#x2F;example.com): https:&#x2F;&#x2F;sergiu.org
&amp;gt; Do you want to enable Sass compilation? [Y&#x2F;n]: y
&amp;gt; Do you want to enable syntax highlighting? [y&#x2F;N]: y
&amp;gt; Do you want to build a search index of the content? [y&#x2F;N]: y

&lt;span style=&quot;font-weight:bold;&quot;&gt;&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;Done! Your site was created in &#x2F;srv&#x2F;sergiu.org&lt;&#x2F;span&gt;

&lt;span style=&quot;font-weight:bold;&quot;&gt;Get started by moving into the directory and using the built-in server: `zola serve`&lt;&#x2F;span&gt;
Visit https:&#x2F;&#x2F;www.getzola.org for the full documentation.
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This creates the following skeleton:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;&#x2F;srv&#x2F;&lt;span style=&quot;font-weight:bold;&quot;&gt;sergiu.org&lt;&#x2F;span&gt; ❱ &lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;tree&lt;&#x2F;span&gt;
.
├── config.toml
├── content
├── sass
├── static
├── templates
└── themes

5 directories, 1 file
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;built-in-web-server&quot;&gt;Built-in web server&lt;a class=&quot;zola-anchor&quot; href=&quot;#built-in-web-server&quot; aria-label=&quot;Anchor link for: built-in-web-server&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You can preview the website quickly using &lt;code&gt;zola serve&lt;&#x2F;code&gt;. I’m using &lt;code&gt;0.0.0.0&lt;&#x2F;code&gt; instead of &lt;code&gt;127.0.0.1&lt;&#x2F;code&gt; in order to be able to access the server from outside the network.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;&#x2F;srv&#x2F;&lt;span style=&quot;font-weight:bold;&quot;&gt;sergiu.org&lt;&#x2F;span&gt; ❱ &lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;zola&lt;&#x2F;span&gt; &lt;span style=&quot;color:#005fd7;&quot;&gt;serve -u 0.0.0.0 -i 0.0.0.0&lt;&#x2F;span&gt;
&lt;span style=&quot;font-weight:bold;&quot;&gt;Building site...&lt;&#x2F;span&gt;
-&amp;gt; Creating 0 pages (0 orphan), 0 sections, and processing 0 images
&lt;span style=&quot;font-weight:bold;&quot;&gt;&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;Done in 5ms.
&lt;&#x2F;span&gt;
Web server is available at http:&#x2F;&#x2F;0.0.0.0:1111

Listening for changes in &#x2F;srv&#x2F;sergiu.org{config.toml, content, sass, static, templates}
Press Ctrl+C to stop
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which results in this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;sergiu.org&#x2F;blog&#x2F;building-this-blog-with-zola&#x2F;welcome-to-zola.png&quot; alt=&quot;welcome-to-zola&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Now, the official documentation suggests a certain &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;documentation&#x2F;content&#x2F;overview&#x2F;&quot;&gt;content structure&lt;&#x2F;a&gt; which is fairly intuitive. What I found more useful is this &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;getzola&#x2F;zola&#x2F;blob&#x2F;master&#x2F;EXAMPLES.md&quot;&gt;list of examples&lt;&#x2F;a&gt;, many of them having the source code publicly available. I personally like the design and structure used by &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.vincentprouillet.com&#x2F;&quot;&gt;Vincent Prouillet&lt;&#x2F;a&gt; (Zola’s creator) which I’ve adopted as a starting point for my website.&lt;&#x2F;p&gt;
&lt;p&gt;All in all, this is the current file structure of this site:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;&#x2F;srv&#x2F;&lt;span style=&quot;font-weight:bold;&quot;&gt;sergiu.org&lt;&#x2F;span&gt; ❱ &lt;span style=&quot;font-weight:bold;color:blue;&quot;&gt;tree&lt;&#x2F;span&gt; &lt;span style=&quot;color:#005fd7;&quot;&gt;-I public&lt;&#x2F;span&gt; &lt;span style=&quot;font-weight:bold;color:grey;&quot;&gt;# exclude the auto-generated &quot;public&quot; dir&lt;&#x2F;span&gt;
.
├── config.toml
├── content
│   └── blog
│       ├── _index.md
│       ├── building-this-blog-with-zola
│       │   ├── index.md
│       │   ├── medium-login-wall.png
│       │   ├── welcome-to-zola.png
│       │   └── zola-welcome.png
│       └── state-of-ghost-on-arch
│           └── index.md
├── sass
│   ├── _base.scss
│   ├── _blog.scss
│   ├── _layout.scss
│   ├── _normalize.scss
│   └── site.scss
├── static
│   ├── Rubik-Regular.ttf
│   └── thesis.pdf
├── templates
│   ├── base.html
│   ├── blog.html
│   ├── index.html
│   └── page.html
└── themes

8 directories, 18 files
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;editing&quot;&gt;Editing&lt;a class=&quot;zola-anchor&quot; href=&quot;#editing&quot; aria-label=&quot;Anchor link for: editing&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Since most content is in the form of Markdown files, I can just &lt;code&gt;ssh&lt;&#x2F;code&gt; into the server and write new content using a text editor.&lt;&#x2F;p&gt;
&lt;p&gt;The content can be updated using &lt;code&gt;zola build&lt;&#x2F;code&gt;. This renders the pages and exports everything as static files in the &lt;code&gt;public&lt;&#x2F;code&gt; dir.&lt;&#x2F;p&gt;
&lt;p&gt;I’ve added this line to my &lt;code&gt;.vimrc&lt;&#x2F;code&gt; to rebuild the site every time I hit &lt;code&gt;\zb&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;vim&quot; style=&quot;background-color:#f5f5f5;color:#1f1f1f;&quot; class=&quot;language-vim &quot;&gt;&lt;code class=&quot;language-vim&quot; data-lang=&quot;vim&quot;&gt;&lt;span style=&quot;color:#b39f04;&quot;&gt;nnoremap &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a2a001;&quot;&gt;&amp;lt;Leader&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;zb :!cd &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c49a39;&quot;&gt;&#x2F;srv&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;sergiu&lt;&#x2F;span&gt;&lt;span style=&quot;color:#668f14;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;org; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b39f04;&quot;&gt;zola&lt;&#x2F;span&gt;&lt;span&gt; build&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a2a001;&quot;&gt;&amp;lt;CR&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This means there’s no “save draft” option. All changes I make while writing a post show up incrementally as I’m making progress. This is good enough for now, but in the long term I want to improve the workflow. A better approach would be to have a separate server which is protected against the outside world and only accessible by me. Once I finish writing a post and I’m happy with the result, I can push the changes to the live server. Storing the files on git is also a common practice with static websites. This is all future work though so I’m not going to throw myself completely down the rabbit hole quite yet.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;deployment&quot;&gt;Deployment&lt;a class=&quot;zola-anchor&quot; href=&quot;#deployment&quot; aria-label=&quot;Anchor link for: deployment&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;As mentioned above, the static site is served by nginx:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;conf&quot; style=&quot;background-color:#f5f5f5;color:#1f1f1f;&quot; class=&quot;language-conf &quot;&gt;&lt;code class=&quot;language-conf&quot; data-lang=&quot;conf&quot;&gt;&lt;span style=&quot;color:#668f14;&quot;&gt;http &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#668f14;&quot;&gt;  [...]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#668f14;&quot;&gt;  server &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;listen &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b3933a;&quot;&gt;80&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;server_name &lt;&#x2F;span&gt;&lt;span&gt;sergiu&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;org;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;root &lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;srv&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;sergiu&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a2a001;&quot;&gt;org&#x2F;public&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;    index&lt;&#x2F;span&gt;&lt;span&gt; index&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;html;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;error_page &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b3933a;&quot;&gt;404 404&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;html;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;    location &#x2F;&lt;&#x2F;span&gt;&lt;span&gt; {
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;try_files &lt;&#x2F;span&gt;&lt;span style=&quot;color:#668f14;&quot;&gt;$uri $uri&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;&#x2F; =&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b3933a;&quot;&gt;404&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 style=&quot;color:#668f14;&quot;&gt;  [...]
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
</description>
      </item>
      <item>
          <title>Putting the Fun in Function Optimization</title>
          <pubDate>Wed, 02 May 2018 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://sergiu.org/blog/putting-the-fun-in-function-optimization/</link>
          <guid>https://sergiu.org/blog/putting-the-fun-in-function-optimization/</guid>
          <description xml:base="https://sergiu.org/blog/putting-the-fun-in-function-optimization/">&lt;p&gt;The problem of finding the maximum (or minimum) of a real function is often encountered in real-life problems. This is especially true when the function describes how close a solution is to some pre-established aim.&lt;&#x2F;p&gt;
&lt;p&gt;We as humans have the natural instinct of searching for better ways to do things:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;finding a shorter route to work&lt;&#x2F;li&gt;
&lt;li&gt;earning a higher grade while studying less&lt;&#x2F;li&gt;
&lt;li&gt;finding a balance between all areas of our lives which leads to highest level of happiness&lt;&#x2F;li&gt;
&lt;li&gt;and the list goes on&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Naturally, not all of these targets are easily quantifiable or achievable, but constructing an appropriate model for such a complex problem is the first step towards solving it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-textbook-way&quot;&gt;The textbook way&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-textbook-way&quot; aria-label=&quot;Anchor link for: the-textbook-way&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;There are &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Mathematical_optimization#Computational_optimization_techniques&quot;&gt;many known methods&lt;&#x2F;a&gt; of finding the maximum (or minimum) of a real function.&lt;&#x2F;p&gt;
&lt;p&gt;Some of the more popular ones - &lt;em&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Gradient_descent&quot;&gt;Gradient Descent&lt;&#x2F;a&gt;, for instance&lt;&#x2F;em&gt; - became known in the mainstream CS community due to their applicability in &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.coursera.org&#x2F;learn&#x2F;machine-learning&quot;&gt;Machine Learning&lt;&#x2F;a&gt; and their simplicity of implementation:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;matlab&quot; style=&quot;background-color:#f5f5f5;color:#1f1f1f;&quot; class=&quot;language-matlab &quot;&gt;&lt;code class=&quot;language-matlab&quot; data-lang=&quot;matlab&quot;&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;function &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;theta&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;J_history&lt;&#x2F;span&gt;&lt;span&gt;] =
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c23f31;&quot;&gt;gradientDescent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;X&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;y&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;theta&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;alpha&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;num_iters&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#7f8989;&quot;&gt;% GRADIENTDESCENT Performs gradient descent to learn theta
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#7f8989;&quot;&gt;%   theta = GRADIENTDESENT(X, y, theta, alpha, num_iters)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#7f8989;&quot;&gt;%   updates theta by taking num_iters gradient steps with
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#7f8989;&quot;&gt;%   learning rate alpha
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;m&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt; = length&lt;&#x2F;span&gt;&lt;span&gt;(y); &lt;&#x2F;span&gt;&lt;span style=&quot;color:#7f8989;&quot;&gt;% number of training examples
&lt;&#x2F;span&gt;&lt;span&gt;J_history&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt; = zeros&lt;&#x2F;span&gt;&lt;span&gt;(num_iters, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b3933a;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;iter&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt; = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b3933a;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt;num_iters
&lt;&#x2F;span&gt;&lt;span&gt;    rsum_0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt; = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b3933a;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    rsum_1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt; = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b3933a;&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;span style=&quot;color:#72ab00;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b3933a;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b3933a;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt;m,
&lt;&#x2F;span&gt;&lt;span&gt;        rsum_0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt; += &lt;&#x2F;span&gt;&lt;span&gt;(X(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b3933a;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt; * &lt;&#x2F;span&gt;&lt;span&gt;theta&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt; - &lt;&#x2F;span&gt;&lt;span&gt;y(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b3933a;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt; * &lt;&#x2F;span&gt;&lt;span&gt;X(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b3933a;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b3933a;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;        rsum_1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt; += &lt;&#x2F;span&gt;&lt;span&gt;(X(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b3933a;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt; * &lt;&#x2F;span&gt;&lt;span&gt;theta&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt; - &lt;&#x2F;span&gt;&lt;span&gt;y(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b3933a;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt; * &lt;&#x2F;span&gt;&lt;span&gt;X(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b3933a;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b3933a;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;end
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    theta&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt; = &lt;&#x2F;span&gt;&lt;span&gt;[theta(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b3933a;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt; - &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b39f04;&quot;&gt;alpha&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt; &#x2F; &lt;&#x2F;span&gt;&lt;span&gt;m)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt; * &lt;&#x2F;span&gt;&lt;span&gt;rsum_0;
&lt;&#x2F;span&gt;&lt;span&gt;             theta(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b3933a;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt; - &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b39f04;&quot;&gt;alpha&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt; &#x2F; &lt;&#x2F;span&gt;&lt;span&gt;m)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt; * &lt;&#x2F;span&gt;&lt;span&gt;rsum_1];
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#7f8989;&quot;&gt;% Save the cost J in every iteration
&lt;&#x2F;span&gt;&lt;span&gt;    J_history(iter)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt; = &lt;&#x2F;span&gt;&lt;span&gt;computeCost(X, y, theta);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;end
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The problem with such methods is their mathematical complexity. It is considerably more difficult to understand the inner workings and intuition behind gradient descent than it is to actually implement it.&lt;&#x2F;p&gt;
&lt;p&gt;Coming up with the algorithm from first principles requires a strong mathematical background. Just opening the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Gradient_descent#Description&quot;&gt;Wikipedia article&lt;&#x2F;a&gt; is enough to scare most programmers away, when they encounter this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;sergiu.org&#x2F;blog&#x2F;putting-the-fun-in-function-optimization&#x2F;gradient-descent-description.png&quot; alt=&quot;gradient-descent-description&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-more-intuitive-way&quot;&gt;A more intuitive way&lt;a class=&quot;zola-anchor&quot; href=&quot;#a-more-intuitive-way&quot; aria-label=&quot;Anchor link for: a-more-intuitive-way&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Luckily, there is a class of heuristic-based optimization techniques which perform on-par with the &lt;strong&gt;mathematically proven™&lt;&#x2F;strong&gt; methods, when tuned properly. Most of these algorithms are heavily inspired from natural phenomena, ranging from the movement of &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Artificial_bee_colony_algorithm&quot;&gt;bees in a colony&lt;&#x2F;a&gt;, to &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Charles_Darwin&quot;&gt;Darwin&lt;&#x2F;a&gt;’s theory of evolution by &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Natural_selection&quot;&gt;natural selection&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;particle-swarm-optimization&quot;&gt;Particle Swarm Optimization&lt;a class=&quot;zola-anchor&quot; href=&quot;#particle-swarm-optimization&quot; aria-label=&quot;Anchor link for: particle-swarm-optimization&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;This particular technique was initially designed as a model to represent the movement of flocks of birds or groups of fish. Later analysis showed that the algorithm was performing optimization.&lt;&#x2F;p&gt;
&lt;p&gt;Assume that we want to minimize a $2$-dimensional real function (this method also works for $n$-dimensional functions). The main idea behind PSO can be described as follows:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A particle represents a potential solution (&lt;em&gt;i.e.&lt;&#x2F;em&gt; a pair $(x, y)$). From this point forward, we will be refering to this pair as the &lt;strong&gt;position&lt;&#x2F;strong&gt; of the particle.&lt;&#x2F;li&gt;
&lt;li&gt;Additionally, each particle is assigned a &lt;strong&gt;velocity&lt;&#x2F;strong&gt; (&lt;em&gt;i.e.&lt;&#x2F;em&gt; a pair $(dx, dy)$).&lt;&#x2F;li&gt;
&lt;li&gt;Initially, a swarm of N randomly placed (or uniformly distributed) particles is generated in the function domain.&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;strong&gt;fitness&lt;&#x2F;strong&gt; of each particle (&lt;em&gt;i.e.&lt;&#x2F;em&gt; how well it performs as a solution) is computed; this is equivalent to the actual value of the given function at the position of each particle. Our aim is to minimize this fitness.&lt;&#x2F;li&gt;
&lt;li&gt;Each particle keeps track of its best previously encountered position. In addition, we also keep track of the best position ever encountered by any particle in the swarm.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The optimization takes place over the span of multiple iterations. Every iteration works like this:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Each particle moves to a new position, by adding its velocity to the current position.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;The velocity is then recomputed as a weighted average of three factors:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;current velocity (weight $\omega$))&lt;&#x2F;li&gt;
&lt;li&gt;the best position of the particle (weight $\phi_{p_{i}}$)&lt;&#x2F;li&gt;
&lt;li&gt;the best position of the entire swarm (weight $\phi_{G}$)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#f5f5f5;color:#1f1f1f;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#7f8989;&quot;&gt;# p and g are randomly generated in [-1.0, 1.0]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#7f8989;&quot;&gt;# they act as mutations
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c23f31;&quot;&gt;updateVelocity&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;p&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;g&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;  deltaParticle &lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.bestPos[i] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.pos[i]
&lt;&#x2F;span&gt;&lt;span&gt;  deltaSwarm &lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.swarm.bestPos[i] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.pos[i]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  newComponent &lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;omega &lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.velocity[i] \
&lt;&#x2F;span&gt;&lt;span&gt;               &lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span&gt;phiP &lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span&gt;p &lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span&gt;deltaParticle \
&lt;&#x2F;span&gt;&lt;span&gt;               &lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span&gt;phiG &lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span&gt;g &lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span&gt;deltaSwarm
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b3933a;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.velocity &lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;(newComponent, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.velocity[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b3933a;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;])
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.velocity &lt;&#x2F;span&gt;&lt;span style=&quot;color:#72ab00;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#5597d6;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.velocity[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b3933a;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;], newComponent)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;The best position for each particle and for the colony are updated.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;There is a bit of work involved in choosing appropriate values for $\omega$, $\phi_{p_{i}}$ and $\phi_{G}$, but this job becomes considerably less difficult after understanding how each of these parameters affects the colony.&lt;&#x2F;p&gt;
&lt;p&gt;This set of rules leads to a tremendously organic behaviour. There is no magic behind the scenes; it’s just particles that explore the problem domain while learning from their past experience and from each other.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;testing&quot;&gt;Testing&lt;a class=&quot;zola-anchor&quot; href=&quot;#testing&quot; aria-label=&quot;Anchor link for: testing&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Wikipedia provides &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Test_functions_for_optimization&quot;&gt;a list of functions&lt;&#x2F;a&gt; designed specifically for evaluating the performance of optimization algorithms. These are the results I obtained on a subset of them:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;mccormick&quot;&gt;McCormick&lt;a class=&quot;zola-anchor&quot; href=&quot;#mccormick&quot; aria-label=&quot;Anchor link for: mccormick&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Formula: $f(x, y) = sin(x+y) + (x-y)^2 - 1.5x + 2.5y + 1$&lt;&#x2F;p&gt;
&lt;p&gt;Global minimum: $ f(-0.54719, -1.54719) = -1.9133 $&lt;&#x2F;p&gt;
&lt;p&gt;Best solution found: $ f(-0.54710, -1.54724) = -1.913223 $&lt;&#x2F;p&gt;
&lt;p&gt;Plot:&lt;&#x2F;p&gt;
&lt;div id=&quot;McCormick&quot; style=&quot;min-width:60%; max-width:60%; min-height:500px; margin: 0 auto;&quot;&gt;&lt;&#x2F;div&gt;
&lt;video width=&quot;auto&quot; height=&quot;auto&quot; style=&quot;max-width:60%; display:block; margin: 0 auto;&quot; controls&gt;
  &lt;source src=&quot;mccormick.webm&quot; type=&quot;video&#x2F;webm&quot;&gt;
Your browser does not support the video tag.
&lt;&#x2F;video&gt;
&lt;p&gt;Notes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;There is a noticeable cluster of particles that gravitate around a local minimum, also visible in the function plot.&lt;&#x2F;li&gt;
&lt;li&gt;A set of $100$ particles and approximately $200$ iterations suffice for finding the global minimum with a precision of $ 10^{-3} $; further improvements require additional iterations.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;eggholder&quot;&gt;Eggholder&lt;a class=&quot;zola-anchor&quot; href=&quot;#eggholder&quot; aria-label=&quot;Anchor link for: eggholder&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Formula: $ f(x, y) = -(y+47) * sin \sqrt {\left | \frac{x}{2} + (y+47)  \right |} - x * sin \sqrt{\left |  x - (y+47) \right |} $&lt;&#x2F;p&gt;
&lt;p&gt;Global minimum: $ f(512, 404.2319) = -959.6407 $&lt;&#x2F;p&gt;
&lt;p&gt;Best solution found: $ f(482.03561, 432.59104) = -956.879905 $&lt;&#x2F;p&gt;
&lt;p&gt;Plot:&lt;&#x2F;p&gt;
&lt;div id=&quot;Eggholder&quot; style=&quot;min-width:60%; max-width:60%; min-height:500px; margin: 0 auto;&quot;&gt;&lt;&#x2F;div&gt;
&lt;video width=&quot;auto&quot; height=&quot;auto&quot; style=&quot;max-width:60%; display:block; margin: 0 auto;&quot; controls&gt;
  &lt;source src=&quot;eggholder.webm&quot; type=&quot;video&#x2F;webm&quot;&gt;
Your browser does not support the video tag.
&lt;&#x2F;video&gt;
&lt;p&gt;Notes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Because of the numerous local minima of this function, we need to start with a larger set of particles ($500$), such that there is a higher chance of at least one particle being &lt;em&gt;on the right track&lt;&#x2F;em&gt; straight from the beginning.&lt;&#x2F;li&gt;
&lt;li&gt;Same as before, most particles tend to form clusters corresponding to local minima. This is a common problem encountered by &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Hill_climbing&quot;&gt;Hill climbing&lt;&#x2F;a&gt; algorithms.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;rastrigin&quot;&gt;Rastrigin&lt;a class=&quot;zola-anchor&quot; href=&quot;#rastrigin&quot; aria-label=&quot;Anchor link for: rastrigin&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Formula: $ f(x) = A*n + \sum_{i=1}^{n} \left [ x_{i}^{2} - A * cos \left ( 2  \pi x_{i} \right )\right ] $ where $A = 10$ and $x$ is an $n$-dimensional vector ($n=2$).&lt;&#x2F;p&gt;
&lt;p&gt;Global minimum: $ f(0, 0) = 0 $&lt;&#x2F;p&gt;
&lt;p&gt;Best solution found: $ f(0.00181, 0.00083) = 0.000785 $&lt;&#x2F;p&gt;
&lt;p&gt;Plot:&lt;&#x2F;p&gt;
&lt;div id=&quot;Rastrigin&quot; style=&quot;min-width:60%; max-width:60%; min-height:500px; margin: 0 auto;&quot;&gt;&lt;&#x2F;div&gt;
&lt;p&gt;Contour:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;sergiu.org&#x2F;blog&#x2F;putting-the-fun-in-function-optimization&#x2F;Rastrigin_Contour.jpg&quot; alt=&quot;Rastrigin Contour&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;video width=&quot;auto&quot; height=&quot;auto&quot; style=&quot;max-width:60%; display:block; margin: 0 auto;&quot; controls&gt;
  &lt;source src=&quot;rastrigin.webm&quot; type=&quot;video&#x2F;webm&quot;&gt;
Your browser does not support the video tag.
&lt;&#x2F;video&gt;
&lt;p&gt;Notes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;There are a couple of noticeable direction changes in the entire swarm (starting at iteration $40$ and $170$). This behavior illustrates the concept of &lt;strong&gt;swarm intelligence&lt;&#x2F;strong&gt;: as soon as a particle finds a new best solution for the colony, all other particles start to follow it.&lt;&#x2F;li&gt;
&lt;li&gt;The final placement of the swarm resembles the grid-like pattern shown in the contour plot.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;easom&quot;&gt;Easom&lt;a class=&quot;zola-anchor&quot; href=&quot;#easom&quot; aria-label=&quot;Anchor link for: easom&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Formula: $ f(x,y) = -cos \left ( x \right ) cos \left ( y \right ) exp \left ( -\left ( \left ( x - \pi \right )^{2} + \left ( y - \pi \right )^{2}   \right ) \right ) $&lt;&#x2F;p&gt;
&lt;p&gt;Global minimum: $ f(\pi, \pi) = -1 $&lt;&#x2F;p&gt;
&lt;p&gt;Best solution found: $ f(3.14158, 3.14163) = -1.000000 $&lt;&#x2F;p&gt;
&lt;p&gt;Plot:&lt;&#x2F;p&gt;
&lt;div id=&quot;Easom&quot; style=&quot;min-width:60%; max-width:60%; min-height:500px; margin: 0 auto;&quot;&gt;&lt;&#x2F;div&gt;
&lt;video width=&quot;auto&quot; height=&quot;auto&quot; style=&quot;max-width:60%; display:block; margin: 0 auto;&quot; controls&gt;
  &lt;source src=&quot;easom.webm&quot; type=&quot;video&#x2F;webm&quot;&gt;
Your browser does not support the video tag.
&lt;&#x2F;video&gt;
&lt;p&gt;Notes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Nice method for approximating the value of $\pi$. :)&lt;&#x2F;li&gt;&lt;&#x2F;li&gt;
&lt;li&gt;In this simulation, I used a relatively large value for $\omega$. As a result, each particle tends to stick more to its current direction, which makes the particles’ paths more distinctive.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;cross-in-tray&quot;&gt;Cross-in-tray&lt;a class=&quot;zola-anchor&quot; href=&quot;#cross-in-tray&quot; aria-label=&quot;Anchor link for: cross-in-tray&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Formula: $ f(x, y) = -(10^{-4}) \left [ \left | sin\left ( x \right )  sin\left ( y \right ) exp \left ( \left | 100 - \frac{\sqrt{x^{2}+y^{2}}}{\pi} \right | \right ) \right | + 1 \right ]^{0.1} $&lt;&#x2F;p&gt;
&lt;p&gt;Global minimum: $ f(\pm1.34941, \pm1.34941) = -2.06261 $&lt;&#x2F;p&gt;
&lt;p&gt;Best solution found: $ f(1.34830, 1.34880) = -2.062612 $&lt;&#x2F;p&gt;
&lt;p&gt;Plot:&lt;&#x2F;p&gt;
&lt;div id=&quot;Cross-in-tray&quot; style=&quot;min-width:60%; max-width:60%; min-height:500px; margin: 0 auto;&quot;&gt;&lt;&#x2F;div&gt;
&lt;video width=&quot;auto&quot; height=&quot;auto&quot; style=&quot;max-width:60%; display:block; margin: 0 auto;&quot; controls&gt;
  &lt;source src=&quot;cross-in-tray.webm&quot; type=&quot;video&#x2F;webm&quot;&gt;
Your browser does not support the video tag.
&lt;&#x2F;video&gt;
&lt;p&gt;Notes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;All 4 global minima are discovered.&lt;&#x2F;li&gt;
&lt;li&gt;Similar to the &lt;a href=&quot;https:&#x2F;&#x2F;sergiu.org&#x2F;blog&#x2F;putting-the-fun-in-function-optimization&#x2F;#rastrigin&quot;&gt;Rastrigin&lt;&#x2F;a&gt; function, the entire swarm changes direction once a better solution is found.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Optimization techniques usually behave really well on real functions, but they are not limited to this scope. I chose this application because it can provide insightful data visualization more easily than other use cases.&lt;&#x2F;p&gt;
&lt;p&gt;The code can be found on &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;harababurel&#x2F;homework&#x2F;blob&#x2F;master&#x2F;sem4&#x2F;ai&#x2F;lab4&#x2F;15.py&quot;&gt;GitHub&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;script type=&quot;text&#x2F;javascript&quot; async&gt;
functions = [
  {
    &#x27;name&#x27;: &#x27;McCormick&#x27;,
    &#x27;xMin&#x27;: -1.5,
    &#x27;xMax&#x27;: 4,
    &#x27;yMin&#x27;: -3,
    &#x27;yMax&#x27;: 4,
    &#x27;step&#x27;: 0.2,
    &#x27;f&#x27;: (x, y) =&gt; Math.sin(x + y) + Math.pow(x - y, 2) - 1.5 * x + 2.5 * y + 1,
  },
  {
    &#x27;name&#x27;: &#x27;Cross-in-tray&#x27;,
    &#x27;xMin&#x27;: -10,
    &#x27;xMax&#x27;: 10,
    &#x27;yMin&#x27;: -10,
    &#x27;yMax&#x27;: 10,
    &#x27;step&#x27;: 0.2,
    &#x27;f&#x27;: (x, y) =&gt; -0.0001 *
        Math.pow(
            Math.abs(
                Math.sin(x) * Math.sin(y) *
                Math.exp(
                    100 -
                    Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)) &#x2F; Math.PI)) +
                1,
            0.1)
  },
  {
    &#x27;name&#x27;: &#x27;Eggholder&#x27;,
    &#x27;xMin&#x27;: -512,
    &#x27;xMax&#x27;: 512,
    &#x27;yMin&#x27;: -512,
    &#x27;yMax&#x27;: 512,
    &#x27;step&#x27;: 8,
    &#x27;f&#x27;: (x, y) =&gt; -(y + 47) * Math.sin(Math.sqrt(Math.abs(x &#x2F; 2 + (y + 47)))) -
        x * Math.sin(Math.sqrt(Math.abs(x - (y + 47)))),
  },
  {
    &#x27;name&#x27;: &#x27;Easom&#x27;,
    &#x27;xMin&#x27;: Math.PI - 8,
    &#x27;xMax&#x27;: Math.PI + 8,
    &#x27;yMin&#x27;: Math.PI - 8,
    &#x27;yMax&#x27;: Math.PI + 8,
    &#x27;step&#x27;: 0.2,
    &#x27;f&#x27;: (x, y) =&gt; -Math.cos(x) * Math.cos(y) *
        Math.exp(-(Math.pow(x - Math.PI, 2) + Math.pow(y - Math.PI, 2))),
  },
  {
    &#x27;name&#x27;: &#x27;Rastrigin&#x27;,
    &#x27;xMin&#x27;: -5.12,
    &#x27;xMax&#x27;: 5.12,
    &#x27;yMin&#x27;: -5.12,
    &#x27;yMax&#x27;: 5.12,
    &#x27;step&#x27;: 0.1,
    &#x27;f&#x27;: (x, y) =&gt; 10 * 2 + Math.pow(x, 2) - 10 * Math.cos(2 * Math.PI * x) +
        Math.pow(y, 2) - 10 * Math.cos(2 * Math.PI * y)
  },
];


function plot(f) {
  var xs = Array.from(
      {length: Math.ceil((f[&#x27;xMax&#x27;] - f[&#x27;xMin&#x27;]) &#x2F; f[&#x27;step&#x27;])},
      (x, i) =&gt; f[&#x27;xMin&#x27;] + i * f[&#x27;step&#x27;]);
  var ys = Array.from(
      {length: Math.ceil((f[&#x27;yMax&#x27;] - f[&#x27;yMin&#x27;]) &#x2F; f[&#x27;step&#x27;])},
      (x, i) =&gt; f[&#x27;yMin&#x27;] + i * f[&#x27;step&#x27;]);
  var zs = [];

  for (let x of xs) {
    heights = [];
    for (let y of ys) {
      heights.push(f[&#x27;f&#x27;](x, y));
    }
    zs.push(heights);
  }

  console.log(f[&#x27;name&#x27;]);
  console.log(xs.length, ys.length, xs.length * ys.length);

  var data = [{
    x: xs,
    y: ys,
    z: zs,
    type: &#x27;surface&#x27;,
    showscale: false,
    colorscale: &#x27;Viridis&#x27;,
  }];

  var layout = {
    title: false,
    autosize: true,
    showlegend: false,
  };

  Plotly.newPlot(f[&#x27;name&#x27;], data, layout);
}

functions.forEach(plot);
&lt;&#x2F;script&gt;
&lt;!-- &lt;script async&gt; --&gt;
&lt;!--   renderMathInElement(document.body); --&gt;
&lt;!-- &lt;&#x2F;script&gt; --&gt;
&lt;&#x2F;div&gt;
</description>
      </item>
    </channel>
</rss>
