<?xml version="1.0" encoding="utf-8" standalone="yes"?>

<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Homepage on SnailShell</title>
  <link>https://powersnail.com/</link><link rel="self" href="https://powersnail.com/index.xml"></link><updated>Fri, 26 Jun 2026 00:00:00 +0000</updated>
  <id>https://powersnail.com/</id>

  <author>
    <name>PowerSnail</name>
  </author>

  <icon>https://powersnail.com/favicon.ico</icon>

  <description>Recent content in Homepage on SnailShell</description>
  <generator>Hugo -- gohugo.io</generator>
  <copyright>en-us</copyright>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">A Myopic Man&amp;rsquo;s Shower in Daylight</title>
    <link rel="alternate">https://powersnail.com/2026/shower-in-daylight/</link>
    <published>Fri, 26 Jun 2026 00:00:00 +0000</published>
    <updated>Fri, 26 Jun 2026 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2026/shower-in-daylight/</id>
    <summary type="html">The sun with a photon takes a shot at me It runs across the atmosphere Evading dust and wings of birds It penetrates the double-paned window And ricochets off crystals falling in threads Losing its way on the lenses steamed opaque I take them off, trading fog for a blur Bare-eyed, I&amp;rsquo;m still bulletproof.</summary>
    <content type="html">&lt;p&gt;The sun with a photon takes a shot at me &lt;br&gt;
It runs across the atmosphere &lt;br&gt;
Evading dust and wings of birds &lt;br&gt;
It penetrates the double-paned window &lt;br&gt;
And ricochets off crystals falling in threads &lt;br&gt;
Losing its way on the lenses steamed opaque &lt;br&gt;
I take them off, trading fog for a blur  &lt;br&gt;
Bare-eyed, I&amp;rsquo;m still bulletproof.&lt;/p&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">Happy Halloween (2025)</title>
    <link rel="alternate">https://powersnail.com/2025/halloween-pumpkin/</link>
    <published>Fri, 31 Oct 2025 00:00:00 +0000</published>
    <updated>Fri, 31 Oct 2025 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2025/halloween-pumpkin/</id>
    <summary type="html">I don&amp;rsquo;t have a costume this year, so here&amp;rsquo;s a painting of mine of a pumpkin.
A watercolor painting of a pumpkin sitting in a field of grass.</summary>
    <content type="html">&lt;p&gt;I don&amp;rsquo;t have a costume this year, so here&amp;rsquo;s a painting of mine of a pumpkin.&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2025/halloween-pumpkin/pumpkin.jpg&#34; alt=&#34;pumpkin&#34;srcset=&#34;https://powersnail.com/2025/halloween-pumpkin/pumpkin-400w.jpg 400w,/2025/halloween-pumpkin/pumpkin-600w.jpg 600w,/2025/halloween-pumpkin/pumpkin-800w.jpg 800w,/2025/halloween-pumpkin/pumpkin-1000w.jpg 1000w,/2025/halloween-pumpkin/pumpkin-1200w.jpg 1200w,/2025/halloween-pumpkin/pumpkin.jpg 1280w&#34; width=&#34;1280&#34;  height=&#34;700&#34; &gt;

    &lt;figcaption&gt;A watercolor painting of a pumpkin sitting in a field of grass.&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;I hope everyone has a great time at this spooky time of year.&lt;/p&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">Claude Haiku 4.5 Released - Quotes and Notes</title>
    <link rel="alternate">https://powersnail.com/2025/claude-4-5-notes/</link>
    <published>Wed, 22 Oct 2025 00:00:00 +0000</published>
    <updated>Wed, 22 Oct 2025 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2025/claude-4-5-notes/</id>
    <summary type="html">On 2025-10-16, Claude Haiku 4.5 was released. It is a smaller, faster model than the previously released Claude Sonnet 4.5.</summary>
    <content type="html">&lt;p&gt;On 2025-10-16, Claude Haiku 4.5 was released. It is a smaller, faster model than the previously released Claude Sonnet 4.5.&lt;/p&gt;
&lt;p&gt;Here are the release notes: &lt;a href=&#34;https://www.anthropic.com/news/claude-haiku-4-5&#34;&gt;https://www.anthropic.com/news/claude-haiku-4-5&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The claim is that Haiku 4.5 is on par with GPT-5 Codex on SWE-bench. This is quite interesting, as in my experience GPT-5 Codex is incredibly slow for complex tasks, but that extra time seems useful, as it produces more accurate results. I&amp;rsquo;m curious whether Haiku 4.5 performs as well on those kinds of tasks as GPT-5 Codex, but faster, though I&amp;rsquo;m doubtful.&lt;/p&gt;
&lt;p&gt;However, even if it is not as good for large, complex tasks, it might still be useful for completing shorter tasks. If we use GPT-5 Codex as the orchestrator, which then dispatches Haiku 4.5 to write individual functions, we might get a speed boost while keeping the benefit of GPT-5 Codex&amp;rsquo;s higher-level insights.&lt;/p&gt;
&lt;p&gt;Compared with its predecessor, Haiku 3.5, Anthropic claims that Haiku 4.5 offers better capabilities in agentic coding and computer use (for example, operating browsers). Anthropic acknowledges that the model is not a &amp;ldquo;frontier&amp;rdquo; model but is suitable for agentic work, which suggests that Anthropic encourages the same kind of architecture where a large model serves as the orchestrator and a smaller model handles lower-level work.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It is not a frontier model, but its high levels of intelligence and speed make it appropriate for a wide variety of “agentic” uses, including where multiple instances of the model complete tasks in parallel.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Haiku 4.5 is also supposed to have better safety and alignment.&lt;/p&gt;
&lt;p&gt;Haiku 4.5 provides an &amp;ldquo;extended thinking mode&amp;rdquo; in which it follows a chain of thought before replying. I think the reason more models (even smaller, faster models) are becoming &amp;ldquo;reasoning&amp;rdquo; models is that accuracy on complex problems requires more time and tokens. To alleviate this slowness, Anthropic launches another instance of Haiku 4.5 to summarize the thoughts if the chain of thought gets too long.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[&amp;hellip;] agentic episodes in reinforcement learning more frequently encounter physical context-window
limits.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is an interesting observation, and their solution is to make the model &amp;ldquo;aware&amp;rdquo; of this limitation during training. They claim that the model becomes more careful about when to &amp;ldquo;wrap things up&amp;rdquo; as the limit approaches.&lt;/p&gt;
&lt;p&gt;I had once before encountered agents exhausting the context window when porting a Next.js backend to Python with GPT-5 Codex. I&amp;rsquo;m not sure this awareness will help, as I suspect that when dealing with tasks that involve a huge amount of input (e.g., coding in a large codebase), the application layer must also take responsibility for feeding data into the model more judiciously. At least the model probably won&amp;rsquo;t exhaust its context window by outputting too much.&lt;/p&gt;
&lt;p&gt;Sources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.anthropic.com/news/claude-haiku-4-5&#34;&gt;https://www.anthropic.com/news/claude-haiku-4-5&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://assets.anthropic.com/m/99128ddd009bdcb/Claude-Haiku-4-5-System-Card.pdf&#34;&gt;https://assets.anthropic.com/m/99128ddd009bdcb/Claude-Haiku-4-5-System-Card.pdf&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">Firefox 137 Nvidia Hardware Decoding</title>
    <link rel="alternate">https://powersnail.com/2025/firefox-137-nvidia-hardware-decoding/</link>
    <published>Tue, 29 Apr 2025 00:00:00 +0000</published>
    <updated>Tue, 29 Apr 2025 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2025/firefox-137-nvidia-hardware-decoding/</id>
    <summary type="html">Recently, I&amp;rsquo;ve noticed that I don&amp;rsquo;t have hard decoding enabled in Firefox (my machine uses openSUSE Tumbleweed, and proprietary driver 570 for GTX 2080 video card).</summary>
    <content type="html">&lt;p&gt;Recently, I&amp;rsquo;ve noticed that I don&amp;rsquo;t have hard decoding enabled in Firefox (my machine uses openSUSE Tumbleweed, and proprietary driver 570 for GTX 2080 video card). On &lt;code&gt;about:support&lt;/code&gt; page, the media section shows the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Codec   Software    Hardware
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;H264	Supported	Unsupported
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;VP9	    Supported	Unsupported
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;VP8	    Supported	Unsupported
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;AV1	    Supported	Unsupported
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;HEVC	Supported	Unsupported
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;AAC	    Supported	Unsupported
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;MP3	    Supported	Unsupported
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Opus	Supported	Unsupported
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Vorbis	Supported	Unsupported
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;FLAC	Supported	Unsupported
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Wave	Supported	Unsupported&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s a bit disappointing; GTX 2080 certainly have the capability of doing some hardware decoding, and I use it for my Jellyfin installation hosted on the same machine. See &lt;a href=&#34;https://powersnail.com/2023/jellyfin-nvidia-docker/&#34;&gt;this post&lt;/a&gt; on how I set it up.&lt;/p&gt;
&lt;p&gt;To be fair, videos play fine in Firefox&amp;mdash;with software decoding I presume, and I don&amp;rsquo;t often watch YouTube on my PC, so I&amp;rsquo;m not entirely sure when this has been turned off. Some forum posts say that it is new as of Firefox 137, and some suggest that hardware decoding has been broken since 136. See &lt;a href=&#34;https://forum.manjaro.org/t/firefox-137-0-no-longer-plays-any-videos-for-me-after-switching-from-136/176606/1&#34;&gt;https://forum.manjaro.org/t/firefox-137-0-no-longer-plays-any-videos-for-me-after-switching-from-136/176606/1&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After fiddling around a bit with all the various solutions floating around these posts, I found that what I was missing was the &lt;code&gt;libva-nvidia-driver&lt;/code&gt; package. This package is not in the default openSUSE repository, nor is it in the proprietary driver repository; instead it is still in an experimental repository: &lt;a href=&#34;https://build.opensuse.org/package/show/X11%3AXOrg/libva-nvidia-driver&#34;&gt;https://build.opensuse.org/package/show/X11%3AXOrg/libva-nvidia-driver&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To install it (if you are okay with using an experimental package), run&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;opi libva-nvidia-driver&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&amp;hellip;and choose the &lt;code&gt;X11:XOrg&lt;/code&gt; repository as the source. Obligatory reminder: an experimental package comes with the titular caveat of being experimental, and it is your judgement call whether to trust its reliability and compatibility with other packages in the main repo. Also, keep an eye on whether it gets eventually merged into the main repo.&lt;/p&gt;
&lt;p&gt;After getting the package installed, I now see in the Media section:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Codec   Software    Hardware
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;H264	Supported	Supported
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;VP9	    Supported	Supported
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;VP8	    Supported	Supported
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;AV1	    Supported	Unsupported
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;HEVC	Supported	Supported
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;AAC	    Supported	Unsupported
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;MP3	    Supported	Unsupported
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Opus	Supported	Unsupported
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Vorbis	Supported	Unsupported
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;FLAC	Supported	Unsupported
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Wave	Supported	Unsupported&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Hooray! Good enough for me, having H264, VP8/9, and HEVC enabled are all I could ask for.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;There are loads of solutions proposed on forums and Reddit. I did some further experiments on what are the pre-requisite to actually put &lt;code&gt;libva-nvidia-driver&lt;/code&gt; into use.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;ffmpeg&lt;/code&gt; needs to be installed;&lt;/li&gt;
&lt;li&gt;NVIDIA DRM needs to be enabled (which I enable with a kernel parameter &lt;code&gt;nvidia_drm.modeset=1&lt;/code&gt;);&lt;/li&gt;
&lt;li&gt;You need to toggle &lt;code&gt;media.hardware-video-decoding.force-enabled&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; in &lt;code&gt;about:config&lt;/code&gt;. With this being false, hardware decoding support all revert back to Unsupported.&lt;/li&gt;
&lt;li&gt;It&amp;rsquo;s not necessary to touch &lt;code&gt;media.ffmpeg.vaapi.enabled&lt;/code&gt;, &lt;code&gt;media.av1.enabled&lt;/code&gt;, &lt;code&gt;gfx.x11-egl.force-enabled&lt;/code&gt;, or &lt;code&gt;widget.dmabuf.force-enabled&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;All the workarounds involving setting environment variables don&amp;rsquo;t seem to be necessary or effective.&lt;/li&gt;
&lt;/ol&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">&lt;code&gt;tmux&lt;/code&gt; - Edit the Current Pane in Neovim</title>
    <link rel="alternate">https://powersnail.com/2024/tmux-edit-in-neovim/</link>
    <published>Mon, 21 Oct 2024 00:00:00 +0000</published>
    <updated>Mon, 21 Oct 2024 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2024/tmux-edit-in-neovim/</id>
    <summary type="html">TL;DR: I put the following lines into my .tmux.conf:
# Edit current pane in neovim bind e run &amp;#34;tmux capture-pane -S 0 -p -J &amp;gt; /tmp/tmux-edit &amp;amp;&amp;amp; tmux new-window &amp;#39;nvim /tmp/tmux-edit&amp;#39;&amp;#34; bind E run &amp;#34;tmux capture-pane -S - -p -J &amp;gt; /tmp/tmux-edit &amp;amp;&amp;amp; tmux new-window &amp;#39;nvim /tmp/tmux-edit&amp;#39;&amp;#34; Navigation in Neovim ## tmux and neovim are essential parts of my workflow, both of which are very good at being worked on with keyboard only.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: I put the following lines into my &lt;code&gt;.tmux.conf&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Edit current pane in neovim&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;bind&lt;/span&gt; e run &lt;span class=&#34;s2&#34;&gt;&amp;#34;tmux capture-pane -S 0 -p -J &amp;gt; /tmp/tmux-edit &amp;amp;&amp;amp; tmux new-window &amp;#39;nvim /tmp/tmux-edit&amp;#39;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;bind&lt;/span&gt; E run &lt;span class=&#34;s2&#34;&gt;&amp;#34;tmux capture-pane -S - -p -J &amp;gt; /tmp/tmux-edit &amp;amp;&amp;amp; tmux new-window &amp;#39;nvim /tmp/tmux-edit&amp;#39;&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;navigation-in-neovim&#34;&gt;
  Navigation in Neovim
  &lt;a href=&#34;#navigation-in-neovim&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;tmux&lt;/code&gt; and &lt;code&gt;neovim&lt;/code&gt; are essential parts of my workflow, both of which are very good at being worked on with keyboard only.&lt;/p&gt;
&lt;p&gt;Having recently invested in &lt;code&gt;neovim&lt;/code&gt; plugins like &lt;a href=&#34;https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-jump2d.md&#34;&gt;mini.jump2d&lt;/a&gt; and &lt;a href=&#34;https://github.com/ggandor/leap.nvim&#34;&gt;leap.nvim&lt;/a&gt;, I find myself increasingly spoiled. These two plugins, in slightly different ways, provide the capability of moving the cursor to where you are looking at, by identifying that location with a few key strokes. The premise is that if you have somewhere you want the cursor to go, it&amp;rsquo;s likely you are already staring at it, so let&amp;rsquo;s show some labels all around the buffer, and you can type the label right at the destination. &lt;em&gt;leap.nvim&lt;/em&gt; does it by having you type a 2-gram, while &lt;em&gt;mini.jump2d&lt;/em&gt; enumerating locations such as word boundaries, etc.&lt;/p&gt;
&lt;p&gt;The mechanism are better demonstrated by their own docs, but essentially for me, it&amp;rsquo;s like semi-auto eyeball tracking. This kind of navigation might not give you the path of fewest number of keystrokes, but it requires the least amount cognitive load in my experience (compared to reading relative line numbers for example), because it incurs very little context switching in my mind.&lt;/p&gt;
&lt;h2 id=&#34;tweaking-tmux&#34;&gt;
  Tweaking tmux
  &lt;a href=&#34;#tweaking-tmux&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Newly spoiled, I find the experience of moving around in &lt;code&gt;tmux&lt;/code&gt;&amp;rsquo;s copy mode increasingly lacking. I habitually type &lt;code&gt;s&lt;/code&gt; (my binding to &lt;code&gt;leap.nvim&lt;/code&gt;) when I&amp;rsquo;m in &lt;code&gt;tmux&lt;/code&gt;, while staring into the target position waiting for my key stroke hints to show up, as if waving a credit card at tip jar. I want to replicate the leaps and jumps everywhere in the terminal, especially in &lt;code&gt;tmux&lt;/code&gt;. (In fact, I want my entire GUI screen to do this as well: show me all clickable/focusable areas, with a label that I can navigate to; but that&amp;rsquo;s a different story.)&lt;/p&gt;
&lt;p&gt;Instead of trying to replicate the capability in &lt;code&gt;tmux&lt;/code&gt;&amp;mdash;which probably is not only difficult, but also unlikely to provide a 100% identical experience&amp;mdash;I looked for a shortcut, like any respectable lazy engineer would do: I&amp;rsquo;ll just open the current pane in &lt;code&gt;neovim&lt;/code&gt;. This way, I don&amp;rsquo;t have to re-invent the wheel and only have to configure my navigation once in one place.&lt;/p&gt;
&lt;p&gt;In the end, all that needs to be done is a two-line configuration in &lt;code&gt;.tmux.conf&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Edit current pane in neovim&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;bind&lt;/span&gt; e run &lt;span class=&#34;s2&#34;&gt;&amp;#34;tmux capture-pane -S 0 -p -J &amp;gt; /tmp/tmux-edit &amp;amp;&amp;amp; tmux new-window &amp;#39;nvim /tmp/tmux-edit&amp;#39;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;bind&lt;/span&gt; E run &lt;span class=&#34;s2&#34;&gt;&amp;#34;tmux capture-pane -S - -p -J &amp;gt; /tmp/tmux-edit &amp;amp;&amp;amp; tmux new-window &amp;#39;nvim /tmp/tmux-edit&amp;#39;&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Some explanations [@marriottTmux1LinuxManual2024]:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tmux capture-pane&lt;/code&gt; gets the content of the current pane;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-J&lt;/code&gt; unwraps line breaks created by &lt;code&gt;tmux&lt;/code&gt;, this makes stuff like URL, string literals more greppable and more copyable.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-p&lt;/code&gt; pipes it to &lt;code&gt;stdout&lt;/code&gt;, which gets piped into &lt;code&gt;/tmp/tmux-edit&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tmux new-window &#39;nvim /tmp/tmux-edit&#39;&lt;/code&gt; runs neovim in a new tmux window.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-S&lt;/code&gt; specifies the line at which the capture starts; &lt;code&gt;0&lt;/code&gt; is the topmost visible line, while &lt;code&gt;-&lt;/code&gt; is the topmost line in the pane&amp;rsquo;s history. With this, I created two variants of the command: lowercase &lt;kbd&gt;e&lt;/kbd&gt; is bound to capturing the currently visible lines, which I use the most; and capital &lt;kbd&gt;E&lt;/kbd&gt; is bound to capturing the entire history.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2024/tmux-edit-in-neovim/illustration-tmux-neovim.svg&#34; alt=&#34;A sketch that illustrates the concept of this configuration&#34; width=&#34;926.0425818640132&#34;  height=&#34;588.4711867724441&#34; style=&#34;max-width: 100%; height: auto&#34; width=&#34;926.0425818640132&#34;  height=&#34;588.4711867724441&#34; &gt;

    &lt;figcaption&gt;Diagram: Piping tmux pane to neovim&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h2 id=&#34;room-for-improvements&#34;&gt;
  Room for Improvements
  &lt;a href=&#34;#room-for-improvements&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;One, this is not going to work if I try to edit two panes at the same time. A more elegant solution is to create a uniquely-named temp file in place of &lt;code&gt;/tmp/tmux-edit&lt;/code&gt;, but that takes away the simplicity of the solution, as we&amp;rsquo;ll have to deal with quoting &amp;amp; escaping of quotation marks inside a shell command, inside an argument to &lt;code&gt;tmux new-window&lt;/code&gt; inside a shell command inside &lt;code&gt;tmux&lt;/code&gt; configuration file, while making sure that the filename variable is expanding at the right stage. It is not going to be fun. I&amp;rsquo;ll settle with no concurrency for now.&lt;/p&gt;
&lt;p&gt;Two, &lt;code&gt;neovim&lt;/code&gt; doesn&amp;rsquo;t necessarily do too well with very, very long lines, and it is entirely possible that somewhere in the pane history, I &lt;code&gt;cat&lt;/code&gt; some minified file by accident.&lt;/p&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">Disable 2.4GHz for iwd</title>
    <link rel="alternate">https://powersnail.com/2024/disable-2-4ghz-for-iwd/</link>
    <published>Sun, 22 Sep 2024 00:00:00 +0000</published>
    <updated>Sun, 22 Sep 2024 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2024/disable-2-4ghz-for-iwd/</id>
    <summary type="html">Debugging an Erratic WIFI Connection ## Recently, I had a problem with the WIFI connection on my Linux workstation: sometimes, the latency fluctuates quite badly, occasionally to the point of going offline completely.</summary>
    <content type="html">&lt;h2 id=&#34;debugging-an-erratic-wifi-connection&#34;&gt;
  Debugging an Erratic WIFI Connection
  &lt;a href=&#34;#debugging-an-erratic-wifi-connection&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Recently, I had a problem with the WIFI connection on my Linux workstation: sometimes, the latency fluctuates quite badly, occasionally to the point of going offline completely. It doesn&amp;rsquo;t happen all the time, though. I could go through a whole day without a single disruption, but when it started acting out, there was seemingly nothing I could do to stop it. Turning the router off and on again, restarting my PC, forgetting and re-adding the network in Network Manager, etc. all ended up futile.&lt;/p&gt;
&lt;p&gt;At first, I thought it was a problem with how the network was configured on my machine. After all, it&amp;rsquo;s Linux, and 90% of the time when something does not function as expected, it&amp;rsquo;s because there&amp;rsquo;s a switch buried in &lt;code&gt;/etc&lt;/code&gt; whose purpose and usage is detailed on ArchWiki that you just need to flip.&lt;/p&gt;
&lt;p&gt;That did not seem to be the case this time. After some painstaking tinkering around&amp;mdash;reading system logs &amp;amp; dmesg logs, diving into NetworkManager&amp;rsquo;s config files, replacing wpa_supplicant with iwd(&lt;a href=&#34;https://iwd.wiki.kernel.org/&#34;&gt;iNet Wireless Daemon&lt;/a&gt;), switching back to wpa_supplicant, switching to IWD yet again&amp;mdash;I made no progress. The fluctuations came and went as it pleased, unaffected by my efforts to adjust the network configurations.&lt;/p&gt;
&lt;p&gt;But I noticed two interesting patterns: 1) when the network is stable, I have about 10ms ping to 1.1.1.1, but when the network is unstable, the best I get is about 20ms; and 2) the latency is fine when NetworkManager shows 1 bar, i.e. the signal is weak; but when I get 3 bars, fluctuation and disconnections occur, which is very counter-intuitive.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;WIFI Signal&lt;/th&gt;
&lt;th&gt;Minimum Ping&lt;/th&gt;
&lt;th&gt;Maximum Ping&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img
    src=&#34;https://powersnail.com/2024/disable-2-4ghz-for-iwd/network-wireless-signal-weak-symbolic.svg&#34; alt=&#34;an wifi icon with one bar signal&#34; width=&#34;22&#34;  height=&#34;22&#34; style=&#34;max-width: 100%; height: auto&#34; width=&#34;22&#34;  height=&#34;22&#34; &gt;
 Weak&lt;/td&gt;
&lt;td&gt;10ms&lt;/td&gt;
&lt;td&gt;15ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img
    src=&#34;https://powersnail.com/2024/disable-2-4ghz-for-iwd/network-wireless-signal-good-symbolic.svg&#34; alt=&#34;an wifi icon with two bar signal&#34; width=&#34;22&#34;  height=&#34;22&#34; style=&#34;max-width: 100%; height: auto&#34; width=&#34;22&#34;  height=&#34;22&#34; loading=&#34;lazy&#34;&gt;
 Strong&lt;/td&gt;
&lt;td&gt;20ms&lt;/td&gt;
&lt;td&gt;1800ms ~ ∞&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;This got me thinking about 5GHz vs 2.4GHz. I knew that 2.4GHz is slower but more penetrative, while 5GHz is the opposite. It must be the case that whenever the network fluctuates, I&amp;rsquo;m connected to the 2.4GHz band. This can be tested by observing the output of &lt;code&gt;sudo iwctl station wlan0 show | grep Frequency&lt;/code&gt; (&lt;code&gt;wlan0&lt;/code&gt; is the name of my wifi adapter in iwd). I ran this command whenever I got the erratic pings, and indeed, it only happened when connected to the 2.4GHz band.&lt;/p&gt;
&lt;p&gt;The next step was figuring out whether that was the PC&amp;rsquo;s fault or the route&amp;rsquo;s. The first thought was that it must be the PC, because my phone had been connecting to the internet just fine, but of course, there was nothing that I did on my phone that was sensitive to latency, so I might not have noticed it. And more importantly, the phone might have a different strategy choosing which band to connect to, and it favors the 5GHz band more the PC does.&lt;/p&gt;
&lt;p&gt;I took my phone, downloaded one of the WIFI analyzer apps, and started towards a corner of the house, watching as 5GHz signal weakened to the point where the phone switched to 2.4GHz. I tried to ping the router, and well, the familiar fluctuations was reproduced on my phone as well.&lt;/p&gt;
&lt;p&gt;The router isn&amp;rsquo;t mine, though. It&amp;rsquo;s one of those ISP provided router and it belongs to my landlord. So the most I can do is to simply disable 2.4GHz.&lt;/p&gt;
&lt;p&gt;It turns out, when I&amp;rsquo;m Googling around, that most people want the other way around: they want to connect to 2.4GHz and disable 5GHz, like &lt;a href=&#34;https://bbs.archlinux.org/viewtopic.php?id=284405&#34;&gt;this&lt;/a&gt;. I think that&amp;rsquo;s because if you are at the edge of 5GHz&amp;rsquo;s effective range, 2.4GHz is usually more stable despite being slower. That is if your 2.4GHz has not gone rogue like mine.&lt;/p&gt;
&lt;h2 id=&#34;how-to-disable-5ghz-in-iwd&#34;&gt;
  How to disable 5GHz in iwd
  &lt;a href=&#34;#how-to-disable-5ghz-in-iwd&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Despite sharing the same SSID (the name you usually see in the list of WIFIs), the 2.4GHz and 5GHz bands of a WIFI, are actually two separate things that can be connected to. The fact that they appear as a unified entity and that our devices can switch between them seamlessly is a feature of convenience.&lt;/p&gt;
&lt;p&gt;Therefore, the first thing I tried was setting the connection&amp;rsquo;s BSSID (which is not shared by different frequency bands) in NetworkManager to the one used by the 5GHz band. Logically, this should tell NetworkManager to specifically look for that 5GHz connection, and not try to switch to its erratic sibling. But it didn&amp;rsquo;t work; because I had iwd as the WIFI backend, which doesn&amp;rsquo;t have the capability of connecting to a BSSID [@sethSOLVEDHowForce2023].&lt;/p&gt;
&lt;p&gt;At the end of the day, there is a switch buried in &lt;code&gt;/etc&lt;/code&gt; whose purpose and usage is detailed on ArchWiki that I can flip [@marcelholtmannIwdconfig5ArchManual2019]:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# /etc/iwd/main.conf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[Rank]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;BandModifier5GHz&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;1.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;BandModifier2_4GHz&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;0.0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;strong&gt;Rank&lt;/strong&gt; section sets the priority of each frequency band with which iwd connects to, and setting it to zero disables it completely.&lt;/p&gt;
&lt;p&gt;To complete the picture, here&amp;rsquo;s my setup:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Machine: A PC that I assembled;&lt;/li&gt;
&lt;li&gt;OS/Distribution: &lt;code&gt;Linux version 6.10.9-1-default (geeko@buildhost) (gcc (SUSE Linux) 14.2.0, GNU ld (GNU Binutils; openSUSE Tumbleweed) 2.43.1.20240828-2) #1 SMP PREEMPT_DYNAMIC Sun Sep 8 13:43:05 UTC 2024 (5af7788)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Network setup: NetworkManager + iwd&lt;/li&gt;
&lt;li&gt;WIFI adapter: Wireless-AC 3168NGW, which came with the motherboard.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;i-probably-need-a-better-router-and-a-better-wifi-adapter-for-the-pc&#34;&gt;
  I probably need a better router, and a better WIFI adapter for the PC
  &lt;a href=&#34;#i-probably-need-a-better-router-and-a-better-wifi-adapter-for-the-pc&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;As mentioned above, when I tested the connection with my phone, my hypothesis was that the phone has a different strategy choosing frequency bands, and it adheres to 5GHz more than the PC, but I was wrong.&lt;/p&gt;
&lt;p&gt;Seemingly, the phone just receives a stronger signal. I&amp;rsquo;m not sure whether this is because the WIFI scanner app calculates RSSI differently from iwd, but if I trust the numbers they gave me, the differences are massive:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;2.4GHz&lt;/th&gt;
&lt;th&gt;5GHz&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PC&lt;/td&gt;
&lt;td&gt;-67dBm&lt;/td&gt;
&lt;td&gt;-71dBm&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phone&lt;/td&gt;
&lt;td&gt;-48dBm&lt;/td&gt;
&lt;td&gt;-53dBm&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Perhaps, in addition to getting a better router with a functional 2.4GHz band, I should also consider getting a more competent WIFI adapter for the PC.&lt;/p&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">Lesson Learned Migrating Registrar</title>
    <link rel="alternate">https://powersnail.com/2024/lesson-learned-migrating-registrar/</link>
    <published>Sun, 28 Jul 2024 00:00:00 +0000</published>
    <updated>Sun, 28 Jul 2024 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2024/lesson-learned-migrating-registrar/</id>
    <summary type="html">I originally registered my domain powersnail.com on Google Domain, which seemed to be a popular and well-made product at the time.</summary>
    <content type="html">&lt;p&gt;I originally registered my domain &lt;code&gt;powersnail.com&lt;/code&gt; on Google Domain, which seemed to be a popular and well-made product at the time. It was all good, until in 2023, the service was announced to terminate and all domains will be transferred to SquareSpace.&lt;/p&gt;
&lt;p&gt;Despite receiving notifications of the news, I procrastinated long enough such that I was already transferred to SquareSpace, when I came about to move away. The interface on SquareSpace was quite bare-bone in functionality and there were reports that its name server was very slow when propagating changes.&lt;/p&gt;
&lt;p&gt;Additionally, Google Domain was convenient for me because I had and need a Google account, but I didn&amp;rsquo;t have a SquareSpace account, and I was not interested in using any of its core product anyway.&lt;/p&gt;
&lt;p&gt;I wanted to move away from it altogether.&lt;/p&gt;
&lt;p&gt;To be precise, there were two things that I&amp;rsquo;d like to change: the name server to CloudFlare and the registrar to porkbun. The former because of its impressive free-tier features, and the latter because it&amp;rsquo;s pretty &lt;em&gt;cool&lt;/em&gt; in a no-bullshit, direct way&amp;mdash;there&amp;rsquo;s something very candid about their UI that just really make me happy.&lt;/p&gt;
&lt;p&gt;The first thing I did was changing the nameserver. It was easy enough, but somehow, the change just was not propagating. It is typical of anything related to DNS to be accompanied by a warning that you may have to wait for a couple of hours, but to be honest, when I was messing with DNS settings in Google Domain, it never took more than a few minutes for the change to propagate. SquareSpace was living up to its reputation of slow propagation and I was growing impatient, so I decided that, well, as long as the change could eventually happen, I might as well proceed.&lt;/p&gt;
&lt;p&gt;So I requested transfer of the domain itself from SquareSpace to porkbun. It was said that the process would take days. Good enough. It was set into motion. I went away.&lt;/p&gt;
&lt;p&gt;It was, then, a very quiet day. I found myself not being bothered by a single email the entire rest of the day, which was odd. It quickly dawned on me that I had broken my custom domain.&lt;/p&gt;
&lt;p&gt;It turns out that the name server was not successfully changed to CloudFlare. On SquareSpace, the name servers were pointing to CloudFlare. For CloudFlare&amp;mdash;and also the rest of the world, the domain was still pointing to SquareSpace&amp;rsquo;s server. It was hard to imagine how it ended up in such a state, but the result was that neither of them were handling the DNS queries, and so everything, from my blog to my email to my personal git server, was effectively down.&lt;/p&gt;
&lt;p&gt;The fact that changing the name server is not atomic came as a surprise to me. I would have thought that SquareSpace&amp;rsquo;s name server would continue to do its job, during the time where the change was still being propagated, or if some error had occurred, it would rollback. But no, it simply stopped responding to DNS queries first, before the rest of the internet ever saw that change, and then my impatience&amp;mdash;initiating the domain transfer too soon&amp;mdash;froze the broken state where nothing was proceeding.&lt;/p&gt;
&lt;p&gt;The transfer was going to take as much as 15 days, and the customer support refused to expedite the process (come on, SquareSpace, even Godaddy allows it). So, I cancelled the transfer first, restored the name server to SquareSpace, which thankfully fixed the DNS situation, and then, re-requested transfer without messing with name server this time.&lt;/p&gt;
&lt;p&gt;Well, here comes the day of radio silence. When the transfer completed, my domain stopped being resolved again, because the moment the domain was off SquareSpace, SquareSpace cut off the name server for that domain. There was also no way to export the DNS records after the transfer. (I don&amp;rsquo;t remember seeing an export options before either, but I could be wrong, since I no longer have access to that UI)&lt;/p&gt;
&lt;p&gt;Luckily, I had an old backup copy of my DNS records exported from Google Domain, which was not fully up to date, but better than creating everything from scratch. I imported the records to CF, and pointed porkbun to CF&amp;rsquo;s server (which happened nearly instantly unlike SquareSpace).&lt;/p&gt;
&lt;p&gt;Finally, it was all working.&lt;/p&gt;
&lt;p&gt;At the end of the day, here are what I learned about doing a domain transfer without down time:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Don&amp;rsquo;t mess with two things at the same time when dealing with domains, especially when something is not in a fully functional state.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When migrating domains, migrate the DNS records off first. Even if the name server change takes forever, wait until it&amp;rsquo;s done.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;There is also the benefit of using a name server that is not also your registrar, so when you transfer the domain, you don&amp;rsquo;t risk the registrar also cut off DNS resolution. I think it isn&amp;rsquo;t unreasonable to expect any sane provider to not cut it off, because these are obviously separate services, but the reality is that they very well might.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And special thanks to SquareSpace for providing a learning opportunity. Had the name server change been swift, or had the name server been available until I disable them, everything would have worked smoothly and I wouldn&amp;rsquo;t even realize that there were lessons to be learned.&lt;/p&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">How to Make Neovim Open PDF and Images External Viewers</title>
    <link rel="alternate">https://powersnail.com/2024/open-binary-files-external/</link>
    <published>Tue, 05 Mar 2024 00:00:00 +0000</published>
    <updated>Tue, 05 Mar 2024 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2024/open-binary-files-external/</id>
    <summary type="html">After some serious attempts to equip my terminal emulator with the ability rendering images, I&amp;rsquo;ve given up on it. My experience is that in 2024, it&amp;rsquo;s still not quite a practical endeavor, at least on my machine with all the CLI tools that I&amp;rsquo;m using, specifically tmux and neovim.</summary>
    <content type="html">&lt;p&gt;After some serious attempts to equip my terminal emulator with the ability rendering images, I&amp;rsquo;ve given up on it. My experience is that in 2024, it&amp;rsquo;s still not quite a practical endeavor, at least on my machine with all the CLI tools that I&amp;rsquo;m using, specifically &lt;code&gt;tmux&lt;/code&gt; and &lt;code&gt;neovim&lt;/code&gt;. There are a handful of image protocols out there made for this purpose, but each comes with enough caveats, or limitations on what terminal/multiplexer/scrolling capabilities that it can work with.&lt;/p&gt;
&lt;p&gt;Still, there is the need to display images and PDFs while I&amp;rsquo;m working, and using &lt;code&gt;neovim&lt;/code&gt; as my main editor, I find it tedious to have to open a preview of a file in another pane by typing out its full path, when there is a perfectly functional fuzzy search capability right there in the editor. It&amp;rsquo;s also annoying when I accidentally select a binary file and &lt;code&gt;neovim&lt;/code&gt; shows me gibberish.&lt;/p&gt;
&lt;p&gt;As a workaround, I set up some auto-commands that trigger external previewers for these files:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;-- Open binary files&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;vim.api&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nvim_create_autocmd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;BufReadCmd&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;pattern&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;*.pdf&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;callback&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kd&#34;&gt;local&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;filename&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vim.fn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;shellescape&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vim.api&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nvim_buf_get_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;vim.cmd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;silent !mupdf &amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;..&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;filename&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;..&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34; &amp;amp;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;vim.cmd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;let tobedeleted = bufnr(&amp;#39;%&amp;#39;) | b# | exe &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;bd! &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; . tobedeleted&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;vim.api&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nvim_create_autocmd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;BufReadCmd&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;pattern&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;*.png&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;*.jpg&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;*.jpeg&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;*.gif&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;*.webp&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;callback&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kd&#34;&gt;local&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;filename&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vim.fn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;shellescape&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vim.api&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nvim_buf_get_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;vim.cmd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;silent !eyestalk &amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;..&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;filename&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;..&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34; &amp;amp;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;vim.cmd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;let tobedeleted = bufnr(&amp;#39;%&amp;#39;) | b# | exe &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;bd! &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; . tobedeleted&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The snippet is predominantly based on &lt;a href=&#34;https://vi.stackexchange.com/questions/7217/how-can-i-cancel-reading-a-file-into-a-buffer-on-bufreadpre&#34;&gt;this Stack Exchange post&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;some-explanations&#34;&gt;
  Some explanations
  &lt;a href=&#34;#some-explanations&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;BufReadCmd&lt;/code&gt;. This function is triggered before the file is loaded into the buffer, and in fact, it is supposed to do the actual work of reading the file. By not doing that work, the reading is avoided. &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; &lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vim.fn.shellescape(vim.api.nvim_buf_get_name(0))&lt;/code&gt;. This line retrieves the name of the current buffer&amp;rsquo;s file using &lt;code&gt;vim.api.nvim_buf_get_name(0)&lt;/code&gt; and then escapes the filename for safe use in a shell command using &lt;code&gt;vim.fn.shellescape()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The trailing &lt;code&gt;&amp;amp;&lt;/code&gt; puts the process of the external program into the background, so the editor is not frozen by it.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vim.cmd(&amp;quot;let tobedeleted = bufnr(&#39;%&#39;) | b# | exe \&amp;quot;bd! \&amp;quot; . tobedeleted&amp;quot;)&lt;/code&gt;. This command first switches the previous buffer to the front, and deletes the buffer of the binary file. &lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;further-work&#34;&gt;
  Further work
  &lt;a href=&#34;#further-work&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The next step is to find or make a fast, general purpose file viewer, so I can open all binary files&amp;mdash;or any file that&amp;rsquo;s not suitable for text-based editing&amp;mdash;in the same app. At the moment, &lt;code&gt;mupdf&lt;/code&gt; is the fastest simple PDF viewer I&amp;rsquo;ve found, at least the fastest among the packages in my system repo.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;Bram Moolenaar. (2024, January 25). VIM REFERENCE MANUAL. &lt;a href=&#34;https://vimhelp.org/autocmd.txt.html#BufReadCmd&#34;&gt;https://vimhelp.org/autocmd.txt.html#BufReadCmd&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;muru. (2016, April 6). Answer to “How can I cancel reading a file into a buffer on BufReadPre?” Vi and Vim Stack Exchange. &lt;a href=&#34;https://vi.stackexchange.com/a/7223&#34;&gt;https://vi.stackexchange.com/a/7223&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;Louwers, B. (2016, April 6). Answer to “How can I cancel reading a file into a buffer on BufReadPre?” Vi and Vim Stack Exchange. &lt;a href=&#34;https://vi.stackexchange.com/a/7236&#34;&gt;https://vi.stackexchange.com/a/7236&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">Hardware Accelerated Jellyfin, Docker Composed, in openSUSE</title>
    <link rel="alternate">https://powersnail.com/2023/jellyfin-nvidia-docker/</link>
    <published>Sun, 12 Mar 2023 00:00:00 +0000</published>
    <updated>Sun, 12 Mar 2023 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2023/jellyfin-nvidia-docker/</id>
    <summary type="html">What is it all about? ## Here is what I&amp;rsquo;m trying to do: I want to watch TV at home.</summary>
    <content type="html">&lt;h2 id=&#34;what-is-it-all-about&#34;&gt;
  What is it all about?
  &lt;a href=&#34;#what-is-it-all-about&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Here is what I&amp;rsquo;m trying to do: I want to watch TV at home. On my hard drive, is a collection of videos, and I&amp;rsquo;d like to stream them from my PC to mobile devices. The PC runs openSUSE, has an NVIDIA card, and Jellyfin&amp;mdash;a sort of self-hosted Netflix&amp;mdash;is my choice for managing the multimedia files and the streaming.&lt;/p&gt;
&lt;h2 id=&#34;why-am-i-running-jellyfin-in-docker&#34;&gt;
  Why am I Running Jellyfin in Docker
  &lt;a href=&#34;#why-am-i-running-jellyfin-in-docker&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;You can run Jellyfin just by itself, un-containerized, and tell it to use the dependencies that are installed by your OS&amp;rsquo;s package manager. It would be more space-efficient. You would need one less moving parts (Docker).&lt;/p&gt;
&lt;p&gt;I run Jellyfin in a Docker container, mainly for the bundled FFmpeg. Jellyfin uses FFmpeg as the underlying tool that does all the heavy-lifting with regard to processing the videos. The problem is that FFmpeg is one of those programs which come with a huge number of compiling options, some of which are turned off by default, some can&amp;rsquo;t be enabled in certain distributions due to licensing issues. These can&amp;rsquo;t be tweaked at runtime. I can compile FFmpeg myself, but first, that defeats the purpose of saving space, and it would be a pain to keep it up to date and resolve compatibility issues between it, the OS, and Jellyfin. Using the official docker image will likely be less of a headache.&lt;/p&gt;
&lt;p&gt;Another reason, applicable to software that deals with the file system, is that there&amp;rsquo;s less of a chance that a bug could affect unrelated files, since Docker only gives it access to specified directories. If Jellyfin messes up, at most my media folder gets obliterated, which I have a backup for, and which is easily rectified when the rest of the file system is left untouched.&lt;/p&gt;
&lt;p&gt;At last, it&amp;rsquo;s easy to put constraints on how many cores Jellyfin can use. My machine has 16 cores, and really, to enable the transcoding of videos for one or two users, no more than 2 or 3 cores are necessary. However, for some reason, when I ran it bare metal, I was never able to enact that restriction, whether through Jellyfin&amp;rsquo;s settings, or some other system tools. Docker, on the other hand, can expose a selected set of cores, which as far as all the transcoding processes know, are all the cores existing.&lt;/p&gt;
&lt;h2 id=&#34;installing-dependencies&#34;&gt;
  Installing Dependencies
  &lt;a href=&#34;#installing-dependencies&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;To install Docker and Docker Compose,&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo zypper in docker docker-compose
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo systemctl &lt;span class=&#34;nb&#34;&gt;enable&lt;/span&gt; --now docker&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To install graphics card drivers (this configuration works only with Nvidia&amp;rsquo;s proprietary drivers), openSUSE has an &lt;a href=&#34;https://en.opensuse.org/SDB:NVIDIA_drivers&#34;&gt;official guide&lt;/a&gt;, and I use what they call &amp;ldquo;the easy way&amp;rdquo;, which means adding a repository that is co-managed by NVIDIA and openSUSE, and installing the driver via &lt;code&gt;zypper&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo zypper addrepo --refresh &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://download.nvidia.com/opensuse/tumbleweed&amp;#34;&lt;/span&gt; NVIDIA
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo zypper in nvidia-video-G06 nvidia-gl-G06&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Do read the guide carefully&lt;/strong&gt;, though, as the instructions differ for different card models. &lt;code&gt;06&lt;/code&gt; is what works for my card, something else might for yours.&lt;/p&gt;
&lt;p&gt;With the proper drivers installed, we also need &lt;em&gt;NVIDIA&amp;rsquo;s Container Toolkit&lt;/em&gt; to make it work with Docker. The slight problem is that NVIDIA doesn&amp;rsquo;t package this toolkit for Tumbleweed, only Leap, so I&amp;rsquo;m taking some risks here to use a library for a not-exactly-compatible distribution. Well, if it works, it works.&lt;/p&gt;
&lt;p&gt;Using the &lt;a href=&#34;https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#installing-on-suse-15&#34;&gt;guide for Leap 15&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo zypper ar &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://nvidia.github.io/libnvidia-container/opensuse-leap15.1/libnvidia-container.repo&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo zypper ref
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo zypper in nvidia-container-toolkit
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo nvidia-ctk runtime configure --runtime&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;docker&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And I restart the PC at this point, just to make sure that all the enabled services are running.&lt;/p&gt;
&lt;h2 id=&#34;composing-docker-for-jellyfin&#34;&gt;
  Composing Docker for Jellyfin
  &lt;a href=&#34;#composing-docker-for-jellyfin&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s what the official Jellyfin guide says:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker pull jellyfin/jellyfin:latest
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;mkdir -p /srv/jellyfin/&lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;config,cache&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker run -d -v /srv/jellyfin/config:/config &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    -v /srv/jellyfin/cache:/cache &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    -v /media:/media &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    --net&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;host &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    jellyfin/jellyfin:latest&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;From the host OS&amp;rsquo;s perspective, the configuration files are stored in &lt;code&gt;/srv/jellyfin/config&lt;/code&gt;, the caches in &lt;code&gt;/srv/jellyfin/cache&lt;/code&gt;, the media files in a hypothetical &lt;code&gt;/media&lt;/code&gt; directory. Just use wherever your media is (&lt;code&gt;-v /path/to/media:/media&lt;/code&gt;). Inside Jellyfin&amp;rsquo;s configuration, all the media files are relative to &lt;code&gt;/media&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We have more parameters to pass in and to better manage these options, a compose file is simpler and cleaner in my opinion than a shell script:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;# docker-compose.yaml&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;version&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;3.3&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;services&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;jellyfin&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;volumes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;/srv/jellyfin/config:/config&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;/srv/jellyfin/cache:/cache&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;/path/to/media:/media&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;network_mode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;host&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;jellyfin/jellyfin:latest&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;cpuset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;13-15&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;environment&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;NVIDIA_DRIVER_CAPABILITIES=all&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;NVIDIA_VISIBLE_DEVICES=all&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;deploy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;resources&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;                &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;reservations&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;                    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;devices&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;                        &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;driver&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;nvidia&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;                          &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;                          &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;capabilities&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;l&#34;&gt;gpu]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To put a restriction on the cores used by Jellyfin, the option &lt;code&gt;cpuset&lt;/code&gt; is used, and I set it to &lt;code&gt;13-15&lt;/code&gt; which exposes the last three cores, sufficient for my personally use.&lt;/p&gt;
&lt;p&gt;To enable hardware acceleration, we give the container permission to use the cards with environment variables (these are for the NVIDIA Container Toolkit). &lt;code&gt;NVIDIA_DRIVER_CAPABILITIES=all&lt;/code&gt; grants permission to all capabilities. &lt;code&gt;NVIDIA_VISIBLE_DEVICES=all&lt;/code&gt; grants permission to all cards. You can fine-tune which card and what capabilities Jellyfin has access to, by following NVIDIA&amp;rsquo;s &lt;a href=&#34;https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/user-guide.html&#34;&gt;guide&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The rest of the options is the Docker Compose&amp;rsquo;s way of giving access of the GPU to the container [@dockerincComposeFileDeploy2023].&lt;/p&gt;
&lt;h2 id=&#34;configuring-nvenc-and-nvdec-in-jellyfin&#34;&gt;
  Configuring NVENC and NVDEC in Jellyfin
  &lt;a href=&#34;#configuring-nvenc-and-nvdec-in-jellyfin&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The model of my graphics card is RTX 2080, which can be checked by running:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nvidia-smi -L  &lt;span class=&#34;c1&#34;&gt;# GPU 0: NVIDIA GeForce RTX 2080&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The encoding and decoding capabilities of the card can be checked on NVIDIA&amp;rsquo;s website: &lt;a href=&#34;https://developer.nvidia.com/video-encode-and-decode-gpu-support-matrix-new&#34;&gt;https://developer.nvidia.com/video-encode-and-decode-gpu-support-matrix-new&lt;/a&gt;. For my 2080, I&amp;rsquo;ve gotten a good list of decode-able codecs (MPEG-1, MPEG-2, VC-1, VP8, VP9, H.264, H.265), and H.264 and H.265 for encoding, which are more than enough. The only thing missing is AV1 support, which is at the moment not that widely used, but whose popularity is on the rise.&lt;/p&gt;
&lt;p&gt;In Jellyfin, in the section &lt;code&gt;Dashboad&amp;gt;Playback&amp;gt;Transcoding&lt;/code&gt;, set &amp;ldquo;Hardware acceleration&amp;rdquo; to &amp;ldquo;Nvidia NVENC&amp;rdquo;, check the boxes for the supported codecs listed above, and tick the options &amp;ldquo;Enable enhanced NVDEC decoder&amp;rdquo;, and &amp;ldquo;Enable hardware encoding&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s important to know which codec to enable, because Jellyfin blindly trusts the configuration, and won&amp;rsquo;t test whether the GPU is actually capable of doing a specific transcoding. If an option were to be mis-selected, there wouldn&amp;rsquo;t be a fallback, and the video would fail to load.&lt;/p&gt;
&lt;h2 id=&#34;how-well-does-it-work&#34;&gt;
  How well does it work?
  &lt;a href=&#34;#how-well-does-it-work&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s the CPU usage&amp;mdash;specifically the usage of core 13, 14, and 15&amp;mdash;when playing a H.265 video, &lt;strong&gt;without&lt;/strong&gt; hardware acceleration:&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2023/jellyfin-nvidia-docker/cpu-usage-no-gpu.webp&#34; alt=&#34;An image showing that the usages of the three cores are above 80% during transcoding&#34;srcset=&#34;https://powersnail.com/2023/jellyfin-nvidia-docker/cpu-usage-no-gpu-400w.webp 400w,/2023/jellyfin-nvidia-docker/cpu-usage-no-gpu-600w.webp 600w,/2023/jellyfin-nvidia-docker/cpu-usage-no-gpu-800w.webp 800w,/2023/jellyfin-nvidia-docker/cpu-usage-no-gpu-1000w.webp 1000w,/2023/jellyfin-nvidia-docker/cpu-usage-no-gpu-1200w.webp 1200w,/2023/jellyfin-nvidia-docker/cpu-usage-no-gpu.webp 1862w&#34; width=&#34;1862&#34;  height=&#34;162&#34; &gt;

    &lt;figcaption&gt;CPU usage without hardware acceleration&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;After enabling hardware acceleration, when playing the same video, the core usages drop to below 40%, and you can see from the &lt;code&gt;nvtop&lt;/code&gt; (a tool which displays GPU usage), that a FFmpeg process is utilizing the GPU. Now, obviously this data is just a snapshot and is noisy, given all the other processes running on the machine. Although I don&amp;rsquo;t have a clean, isolated, long-lasting series of data showing the history of CPU usage, it is my observation that the drop is both significant and consistent through time. For one, it no longer causes FPS to fluctuate, when a video starts to play while I&amp;rsquo;m in the middle of a game.&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2023/jellyfin-nvidia-docker/cpu-usage-with-gpu.webp&#34; alt=&#34;An image showing that the three cores are utilized below 40%&#34;srcset=&#34;https://powersnail.com/2023/jellyfin-nvidia-docker/cpu-usage-with-gpu-400w.webp 400w,/2023/jellyfin-nvidia-docker/cpu-usage-with-gpu-600w.webp 600w,/2023/jellyfin-nvidia-docker/cpu-usage-with-gpu-800w.webp 800w,/2023/jellyfin-nvidia-docker/cpu-usage-with-gpu-1000w.webp 1000w,/2023/jellyfin-nvidia-docker/cpu-usage-with-gpu-1200w.webp 1200w,/2023/jellyfin-nvidia-docker/cpu-usage-with-gpu.webp 1862w&#34; width=&#34;1862&#34;  height=&#34;162&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;CPU usage with hardware acceleration&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2023/jellyfin-nvidia-docker/gpu-usage.webp&#34; alt=&#34;An image showing GPU usage during transcoding, highlighted is a process of FFmpeg utilizing&#34;srcset=&#34;https://powersnail.com/2023/jellyfin-nvidia-docker/gpu-usage-400w.webp 400w,/2023/jellyfin-nvidia-docker/gpu-usage-600w.webp 600w,/2023/jellyfin-nvidia-docker/gpu-usage-800w.webp 800w,/2023/jellyfin-nvidia-docker/gpu-usage-1000w.webp 1000w,/2023/jellyfin-nvidia-docker/gpu-usage-1200w.webp 1200w,/2023/jellyfin-nvidia-docker/gpu-usage.webp 1916w&#34; width=&#34;1916&#34;  height=&#34;1218&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;GPU usage during transcoding&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;And of course, hardware acceleration isn&amp;rsquo;t just making the GPU busier and the CPU idler; another benefit is that, titularly, the video is transcoded faster. This isn&amp;rsquo;t noticeable in the middle of playing a video, because Jellyfin would, like any competent streaming software, transcode the next chunk when you are still watching the previous one.&lt;/p&gt;
&lt;p&gt;It shines when &lt;strong&gt;starting&lt;/strong&gt; a video, and more importantly, when I&amp;rsquo;m &lt;strong&gt;jumping around&lt;/strong&gt; the progress bar. What used to be a few seconds of spinning circles, is now only a slight punctuation. The improvement on snappiness simply by moving the work from CPU to GPU is, frankly speaking, astonishing.&lt;/p&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">My Config File for Downloading Albums from YouTube Music</title>
    <link rel="alternate">https://powersnail.com/2023/youtube-music-album-download/</link>
    <published>Sun, 19 Feb 2023 00:00:00 +0000</published>
    <updated>Sun, 19 Feb 2023 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2023/youtube-music-album-download/</id>
    <summary type="html">The Config File ## Here&amp;rsquo;s the config file:
# yt-dlp.conf # Output format: album/tracks.format -o &amp;#34;%(album,playlist_title)U - [%(playlist_id)s]/%(track_number,playlist_index)s - %(title)U - [%(id)s].</summary>
    <content type="html">&lt;h2 id=&#34;the-config-file&#34;&gt;
  The Config File
  &lt;a href=&#34;#the-config-file&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s the config file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# yt-dlp.conf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Output format: album/tracks.format&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;-o &lt;span class=&#34;s2&#34;&gt;&amp;#34;%(album,playlist_title)U - [%(playlist_id)s]/%(track_number,playlist_index)s - %(title)U - [%(id)s].%(ext)s&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;--windows-filenames 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# --restrict-filenames &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Extract audio&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;-f bestaudio
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;--extract-audio
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Thumbnail squared&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;--convert-thumbnails png
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;--ppa &lt;span class=&#34;s2&#34;&gt;&amp;#34;ThumbnailsConvertor+ffmpeg_o:-c:v png -vf crop=\&amp;#34;&amp;#39;if(gt(ih,iw),iw,ih)&amp;#39;:&amp;#39;if(gt(iw,ih),ih,iw)&amp;#39;\&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;--embed-thumbnail
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Metadata, with playlist number as track number if the latter is missing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;--embed-metadata
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;--parse-metadata &lt;span class=&#34;s2&#34;&gt;&amp;#34;playlist_index:%(track_number)s&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Misc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;--no-overwrites
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;--concurrent-fragments &lt;span class=&#34;m&#34;&gt;4&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;the-explanation&#34;&gt;
  The Explanation
  &lt;a href=&#34;#the-explanation&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id=&#34;output-formats&#34;&gt;
  Output formats.
  &lt;a href=&#34;#output-formats&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;The files are organized into one-directory-per-album, like the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── Bach, J.S.： Sonatas &amp;amp; Partitas - [OLAK5uy_nd-ZT5mVVQ4tFm_6FsJWbj-u6GypaFYe8]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── 01 - J.S. Bach： Sonata for Violin Solo No. 1 in G Minor, BWV 1001 - I. Adagio - [ZePaXgWY7-Q].opus
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── 02 - J.S. Bach： Sonata for Violin Solo No. 1 in G Minor, BWV 1001 - II. Fuga. Allegro - [93p59vL87cE].opus
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── 03 - J.S. Bach： Sonata for Violin Solo No. 1 in G Minor, BWV 1001 - III. Siciliana - [BRssao79MDM].opus
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── 04 - J.S. Bach： Sonata for Violin Solo No. 1 in G Minor, BWV 1001 - IV. Presto - [NP_LSvkqLjg].opus
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── 05 - J.S. Bach： Partita for Violin Solo No. 1 in B Minor, BWV 1002 - Ia. Allemanda - [4C8pA-8Hy8Q].opus
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── 06 - J.S. Bach： Partita for Violin Solo No. 1 in B Minor, BWV 1002 - Ib. Double - [vy43_64aax8].opus
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── 07 - J.S. Bach： Partita for Violin Solo No. 1 in B Minor, BWV 1002 - IIa. Corrente - [yiHc8-quDIc].opus
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The output template: &lt;code&gt;&amp;quot;%(album,playlist_title)U - [%(playlist_id)s]/%(track_number,playlist_index)s - %(title)U - [%(id)s].%(ext)s&amp;quot;&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;%(album,playlist_title)U&lt;/code&gt; tells &lt;code&gt;yt-dlp&lt;/code&gt; to use the album&amp;rsquo;s name, and if that does not exist, use the playlist&amp;rsquo;s title, the trailing &amp;ldquo;U&amp;rdquo; indicating that the string should be normalized.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%(track_number,playlist_index)s&lt;/code&gt; means that the file name begins with the track number, which makes it easier to sort the files, if the file manager or app is not metadata-aware.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%(title)U&lt;/code&gt; is the title normalized.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%(ext)s&lt;/code&gt; is the extension.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%(id)s&lt;/code&gt; and &lt;code&gt;%(playlist_id)s&lt;/code&gt; are the unique ID that YouTube assigns to the file and the playlist respectively, which might be useful if later I need to get more data from YouTube.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Sanitizing filenames&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;--restrict-filenames&lt;/code&gt; sanitizes the string of illegal characters. Some file systems support more characters than others, so in theory, it makes sense to err on the side of caution. However, this flag replaces all non-ASCII characters and even special ASCII characters with underscores, which is way too aggressive. While it makes file systems very happy, (an incompatibility is basically impossible), all titles, except the pure English ones, get mangled. &amp;ldquo;Dvořák&amp;rdquo; becomes &amp;ldquo;Dvor_k&amp;rdquo;, &amp;ldquo;Ysaÿe&amp;rdquo; now read &amp;ldquo;Ysa_e&amp;rdquo;, and some titles started making funny faces: &lt;code&gt;-___-&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;--windows-filenames&lt;/code&gt; does exactly what it says on the tin: it makes the string Windows-compatible. I&amp;rsquo;d prefer if it is a little bit more aggressive, for instance, removing &lt;code&gt;&amp;amp;&lt;/code&gt; which some cloud drives don&amp;rsquo;t support, but it&amp;rsquo;s a good enough trade-off.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;metadata&#34;&gt;
  Metadata
  &lt;a href=&#34;#metadata&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;--embed-metadata&lt;/code&gt; tells &lt;code&gt;yt-dlp&lt;/code&gt; to embed metadata. Some albums don&amp;rsquo;t have the proper track number set up, which means that when you import the files into a music player, the order of the album gets scrambled up.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;--parse-metadata &amp;quot;playlist_index:%(track_number)s&amp;quot;&lt;/code&gt; uses the playlist index, which should always be present when downloading a playlist, to fill the track number.&lt;/p&gt;
&lt;h3 id=&#34;thumbnails&#34;&gt;
  Thumbnails
  &lt;a href=&#34;#thumbnails&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--embed-thumbnail&lt;/code&gt; tells &lt;code&gt;yt-dlp&lt;/code&gt; to embed a thumbnail;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--convert-thumbnails png&lt;/code&gt; indicates that the format of the thumbnail should be &lt;code&gt;png&lt;/code&gt;. &lt;code&gt;webp&lt;/code&gt; is possibly the best image format available in &lt;code&gt;yt-dlp&lt;/code&gt;, but its popularity being so recent, I&amp;rsquo;m wary of its compatibility with music players. Either &lt;code&gt;png&lt;/code&gt; or &lt;code&gt;jpeg&lt;/code&gt; should be fine.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By default, YouTube provides a padded, rectangular image. To cut off the padding, we can use &lt;code&gt;ffmpeg&lt;/code&gt; in post-processing. In this &lt;a href=&#34;https://github.com/yt-dlp/yt-dlp/issues/429&#34;&gt;Github Issue&lt;/a&gt;, pukkandan(2021) gave a solution: &lt;code&gt;--ppa &amp;quot;EmbedThumbnail+ffmpeg_o:-c:v mjpeg -vf crop=\&amp;quot;&#39;if(gt(ih,iw),iw,ih)&#39;:&#39;if(gt(iw,ih),ih,iw)&#39;\&amp;quot;&amp;quot;&lt;/code&gt;. But on my machine, &lt;code&gt;yt-dlp&lt;/code&gt; seems to ignore this instruction. Even with &lt;code&gt;--verbose&lt;/code&gt; turned on, I could see no log about cropping the thumbnail, and if I mangle the command deliberately, no error is produced, either. All I get is the same padded rectangular image in the end.&lt;/p&gt;
&lt;p&gt;According to &lt;code&gt;yt-dlp&lt;/code&gt;&amp;rsquo;s README:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Supported PP are: Merger, ModifyChapters, SplitChapters, ExtractAudio, VideoRemuxer, VideoConvertor, Metadata, EmbedSubtitle, &lt;strong&gt;EmbedThumbnail&lt;/strong&gt;, SubtitlesConvertor, &lt;strong&gt;ThumbnailsConvertor&lt;/strong&gt;, FixupStretched, FixupM4a, FixupM3u8, FixupTimestamp and FixupDuration.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;EmbedThumbnail&lt;/code&gt; and &lt;code&gt;ThumbnailsConvertor&lt;/code&gt; must be the two relevant options, so I gave the latter a try: &lt;code&gt;--ppa &amp;quot;ThumbnailsConvertor+ffmpeg_o:-c:v png -vf crop=\&amp;quot;&#39;if(gt(ih,iw),iw,ih)&#39;:&#39;if(gt(iw,ih),ih,iw)&#39;\&amp;quot;&amp;quot;&lt;/code&gt;. And, &lt;em&gt;hooray&lt;/em&gt;, it works!&lt;/p&gt;
&lt;p&gt;My guess is that there&amp;rsquo;s some sort of conflict amongst the sequence of converting the image to the right format, embedding the image, and post-processing the image. In a way, I think it makes sense that thumbnail convertor post processor is the right option here, as it implies that we are processing &lt;strong&gt;after the conversion&lt;/strong&gt; and &lt;strong&gt;before the embedding&lt;/strong&gt;, whereas post-processing &lt;code&gt;EmbedThumbnail&lt;/code&gt; would suggest that we are cropping after the embedding occurs, which would be rather not useful. But this is just a speculation. Without digging into the code, it&amp;rsquo;s impossible to tell what exactly is happening here.&lt;/p&gt;
&lt;h3 id=&#34;miscellaneous&#34;&gt;
  Miscellaneous
  &lt;a href=&#34;#miscellaneous&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;--no-overwrites&lt;/code&gt;: Don&amp;rsquo;t overwrite files.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;--concurrent-fragments 4&lt;/code&gt;: Download 4 fragments concurrently to speed up the process.&lt;/p&gt;
&lt;h2 id=&#34;references&#34;&gt;
  References
  &lt;a href=&#34;#references&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;pukkandan. (2021, June 23). &lt;em&gt;Comment on [Feature Request] Crop to square thumbnail when embedding in MP3s&lt;/em&gt;. &lt;a href=&#34;https://github.com/yt-dlp/yt-dlp/issues/429#issuecomment-866836396&#34;&gt;[Feature Request] Crop to square thumbnail when embedding in MP3s · Issue #429 · yt-dlp/yt-dlp · GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;yt-dlp. (2023). &lt;em&gt;Yt-dlp&lt;/em&gt; [Python]. yt-dlp. &lt;a href=&#34;https://github.com/yt-dlp/yt-dlp&#34;&gt;GitHub - yt-dlp/yt-dlp: A youtube-dl fork with additional features and fixes&lt;/a&gt; (Original work published 2020)&lt;/p&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">Setting Wallpapers for Multiple Monitors through DBus for KDE Plasma</title>
    <link rel="alternate">https://powersnail.com/2023/set-plasma-wallpaper/</link>
    <published>Wed, 08 Feb 2023 00:00:00 +0000</published>
    <updated>Wed, 08 Feb 2023 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2023/set-plasma-wallpaper/</id>
    <summary type="html">The Problem ## KDE Plasma is my favorite Linux DE, and it has its quirks and warts. The support for multiple monitors, for example, is fairly buggy at times, especially when monitors are turned on and off.</summary>
    <content type="html">&lt;h2 id=&#34;the-problem&#34;&gt;
  The Problem
  &lt;a href=&#34;#the-problem&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;KDE Plasma is my favorite Linux DE, and it has its quirks and warts.
The support for multiple monitors, for example, is fairly buggy at times,
especially when monitors are turned on and off.
The way it deals with multiple monitors seems to be based on some sort of
numerical index that doesn&amp;rsquo;t map itself to the monitors&amp;rsquo; UUIDs, so
when the configuration changes, desktop settings can be shifted around.&lt;/p&gt;
&lt;p&gt;I have wallpapers of different shapes on each monitor, because my left
monitor is vertical, the right horizontal, and they get messed up when
the machine resumes from sleep or when the monitors are turned off manually.
There appears to be no way of tying a wallpaper to a physical monitor. So, I have
to frequently reset the appropriate wallpapers.&lt;/p&gt;
&lt;p&gt;Plasma already provides a command-line tool for setting wallpaper:
&lt;code&gt;plasma-apply-wallpaperimage&lt;/code&gt;, but it doesn&amp;rsquo;t have the ability to address each
monitor either.&lt;/p&gt;
&lt;h2 id=&#34;the-solution&#34;&gt;
  The Solution
  &lt;a href=&#34;#the-solution&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Fortunately, there&amp;rsquo;s a Band-Aid for every wart, if you are comfortable making
your own Band-Aid. And in this case, my problem can be &amp;ldquo;fixed&amp;rdquo; by resetting
the wallpapers with a script.&lt;/p&gt;
&lt;p&gt;Plasma can be scripted with JavaScript through its DBus interface, and there&amp;rsquo;s
a fairly comprehensive documentation (The KDE Community, 2023).&lt;/p&gt;
&lt;p&gt;The first step is getting the desktops in a deterministic order.
Desktops can be retrieved by a global function &lt;code&gt;desktops()&lt;/code&gt; which &amp;ldquo;returns an
array of all desktops that currently exist&amp;rdquo;(The KDE Community, 2023).
Each &lt;code&gt;Desktop&lt;/code&gt; object has a &lt;code&gt;screen&lt;/code&gt; property, a numerical ID of the
associated monitor, but since Plasma doesn&amp;rsquo;t provide any hardware information or
stable ID of the monitor, the only way to sort the monitors deterministically
seems to be using the screen&amp;rsquo;s position.
We sort them from left to right, which is both deterministic, and fairly
intuitive from the human user&amp;rsquo;s perspective, arguably more so than UUIDs.
Furthermore, since we are setting wallpapers in the order of the monitors, we
can also rule out &lt;code&gt;Desktop&lt;/code&gt; objects with no associated screen.
These ideas are stolen from the
&lt;a href=&#34;https://github.com/hhannine/superpaper/blob/219f00aec19a4f0697e37663875eccbfa19b502b/superpaper/wallpaper_processing.py#L687&#34;&gt;superpaper project&lt;/a&gt;
(Hänninen, 2019).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;getDesktops&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;desktops&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;filter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;screen&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;sort&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;screenGeometry&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;screen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;left&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;screenGeometry&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;screen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;left&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The second piece of puzzle is setting the wallpaper to a &lt;code&gt;Desktop&lt;/code&gt; object:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;setWallpaper&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;desktop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;desktop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;wallpaperPlugin&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;org.kde.image&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;desktop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;currentConfigGroup&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;Array&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Wallpaper&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;org.kde.image&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;General&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;desktop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;writeConfig&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Image&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To assign a list of images to all the desktops one by one:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// Imagine we have a variable called imageList, an array containing the 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// paths of the image files.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;getDesktops&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;().&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;forEach&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;desktop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;setWallpaper&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;desktop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;imageList&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;imageList&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To set one wallpaper for one specific desktop:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// Assume the variable `desktop_id` is the (0-based) index of the
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// monitor, counting from left to right.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// And the variable `image_path` being the path to the image.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;setWallpaper&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;getDesktops&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;desktop_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;image_path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;dbus-interface&#34;&gt;
  DBus Interface
  &lt;a href=&#34;#dbus-interface&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;To run this script, we use the DBus Interface of Plasma, which provides a function
called &lt;code&gt;evaluateScript&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;qdbus org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript &lt;span class=&#34;s2&#34;&gt;&amp;#34;...&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&amp;hellip;or invoke it with your favorite DBus tooling.&lt;/p&gt;
&lt;h2 id=&#34;parameterize&#34;&gt;
  Parameterize
  &lt;a href=&#34;#parameterize&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;evaluateScript&lt;/code&gt; only accepts a self-contained script.
You can hard code the path of the images, but there&amp;rsquo;s no way to supply the image
paths as arguments to it, so some sort of string manipulation is required if you
want to point Plasma to some arbitrary image.&lt;/p&gt;
&lt;p&gt;For me, someone whose home directory is already filled with various Python
glues and &lt;em&gt;ad hoc&lt;/em&gt; scripts, nothing beats some composable &lt;em&gt;f-strings&lt;/em&gt;, string
replacements, and a nice familiar command-line interface.
Any language good with string manipulation and a convenient DBus interface is
a suitable tool for this step.
Or, alternatively, you could also leave the path hard-coded, and place or link
different images to that path before calling the script.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s my script. I can set wallpapers to all the desktops by calling
&lt;code&gt;python wallpaper.py all image1.jpg image2.jpg ...&lt;/code&gt;, and set wallpaper for the 2nd
monitor from the left with &lt;code&gt;python wallpaper.py one 1 image1.jpg&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;dbus&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;typer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;SCRIPT_GET_DESKTOPS&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;function getDesktops() {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;    return desktops()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;        .filter(d =&amp;gt; d.screen != -1)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;        .sort((a, b) =&amp;gt; screenGeometry(a.screen).left - screenGeometry(b.screen).left);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;SCRIPT_SET_WALLPAPER&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;function setWallpaper(desktop, path) {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;    desktop.wallpaperPlugin = &amp;#34;org.kde.image&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;    desktop.currentConfigGroup = Array(&amp;#34;Wallpaper&amp;#34;, &amp;#34;org.kde.image&amp;#34;, &amp;#34;General&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;    desktop.writeConfig(&amp;#34;Image&amp;#34;, path)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;SCRIPT_ALL&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SCRIPT_GET_DESKTOPS&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SCRIPT_SET_WALLPAPER&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;const imageList = IMAGE_LIST;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;getDesktops().forEach((desktop, i) =&amp;gt; setWallpaper(desktop, imageList[i % imageList.length]));
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;SCRIPT_ONE&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SCRIPT_GET_DESKTOPS&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SCRIPT_SET_WALLPAPER&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;setWallpaper(getDesktops()[DESKTOP_ID], IMAGE);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;quote&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#39;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#39;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;plasma_dbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;bus&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dbus&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SessionBus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;plasma&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dbus&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Interface&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;bus&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get_object&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;org.kde.plasmashell&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/PlasmaShell&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dbus_interface&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;org.kde.PlasmaShell&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;plasma&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;app&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;typer&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Typer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@app.command&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;all&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;image_path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;generate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;bool&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;image_list_string&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;[&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;join&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;quote&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;p&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;image_path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;script&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SCRIPT_ALL&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;replace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;IMAGE_LIST&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;image_list_string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;generate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;script&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;plasma_dbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;evaluateScript&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;script&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@app.command&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;one&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;desktop_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;image_path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;generate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;bool&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;script&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SCRIPT_ONE&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;replace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;IMAGE&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;quote&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;image_path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;replace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;DESKTOP_ID&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;desktop_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;generate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;script&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;plasma_dbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;evaluateScript&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;script&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;vm&#34;&gt;__name__&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;app&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;references&#34;&gt;
  References
  &lt;a href=&#34;#references&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Hänninen, H. (2019). &lt;em&gt;Superpaper&lt;/em&gt; [Python]. &lt;a href=&#34;https://github.com/hhannine/superpaper/blob/219f00aec19a4f0697e37663875eccbfa19b502b/superpaper/wallpaper_processing.py&#34;&gt;superpaper/wallpaper_processing.py at 219f00aec19a4f0697e37663875eccbfa19b502b · hhannine/superpaper · GitHub&lt;/a&gt; (Original work published 2019)&lt;/p&gt;
&lt;p&gt;The KDE Community. (2023). &lt;em&gt;API documentation for Plasma scripting API&lt;/em&gt;. Developer. &lt;a href=&#34;https://develop.kde.org/docs/extend/plasma/scripting/api/&#34;&gt;API documentation | Developer&lt;/a&gt;&lt;/p&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">TIL: HTML Has a &lt;code&gt;&amp;lt;time&amp;gt;&lt;/code&gt; Tag</title>
    <link rel="alternate">https://powersnail.com/2022/til-html-time-tag/</link>
    <published>Sat, 10 Dec 2022 09:41:12 +0000</published>
    <updated>Sat, 10 Dec 2022 09:41:12 +0000</updated>
    
    <id>https://powersnail.com/2022/til-html-time-tag/</id>
    <summary type="html">Today I learned that HTML has a &amp;lt;time&amp;gt; tag which supplements a written date and time with a machine-readable format.1 Supposedly, this helps with parsability, and in turn, good for accessibility.</summary>
    <content type="html">&lt;p&gt;Today I learned that HTML has a &lt;code&gt;&amp;lt;time&amp;gt;&lt;/code&gt; tag which supplements a written date and time with a machine-readable format.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; Supposedly, this helps with parsability, and in turn, good for accessibility. I&amp;rsquo;ve added this into my Hugo template for metadata.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{{- $isoFormat := &amp;#34;2006-01-02T15:04:05&amp;#34; -}}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{{- $humanFormat := &amp;#34;02 Jan 2006&amp;#34; -}}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;time&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;datetime&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;{{ .Params.date.Format $isoFormat }}&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;{{ .Params.date.Format $humanFormat }}&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;MDN Web Docs. &lt;em&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time&#34;&gt;https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time&lt;/a&gt;&lt;/em&gt;&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">Engage the Pinky During Bow Change</title>
    <link rel="alternate">https://powersnail.com/2022/engage-pinky-in-bow-change/</link>
    <published>Tue, 22 Nov 2022 00:00:00 +0000</published>
    <updated>Tue, 22 Nov 2022 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2022/engage-pinky-in-bow-change/</id>
    <summary type="html">Nathan Cole talking about shifting the balance to the pinky during one of his master classes.[^nathan] During one of his masterclasses, Nathan Cole was helping a student with landing the a soft note after a series of spiccato.</summary>
    <content type="html">&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/images/nathan-cole.webp&#34; alt=&#34;A picture of violinist Nathan Cole playing during his master class, in green T-shirt.&#34;srcset=&#34;https://powersnail.com/images/nathan-cole-400w.webp 400w,/images/nathan-cole-600w.webp 600w,/images/nathan-cole-800w.webp 800w,/images/nathan-cole-1000w.webp 1000w,/images/nathan-cole-1200w.webp 1200w,/images/nathan-cole.webp 1280w&#34; width=&#34;1280&#34;  height=&#34;591&#34; &gt;

    &lt;figcaption&gt;Nathan Cole talking about shifting the balance to the pinky during one of his master classes.[^nathan]&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;During one of his masterclasses, &lt;a href=&#34;https://www.natesviolin.com/&#34;&gt;Nathan Cole&lt;/a&gt; was helping a student with landing the a soft note after a series of &lt;em&gt;spiccato&lt;/em&gt;. She couldn&amp;rsquo;t get that note &lt;em&gt;piano&lt;/em&gt; enough, because the bow coming down from the air carried its own momentum that was out of her control. Nathan offered two major insights: first, don&amp;rsquo;t think of it as &amp;ldquo;landing&amp;rdquo;, but instead, a rolling motion that morphs into coasting rather than sticking a landing; and second, engage the pinky to lighten weight of the bow, so the bow keeps its angle constant. What she had been doing up to that point, was raising her arm to lighten the note, which lifted the frog of the bow, causing the bow to rotate slightly, the tip to drop, and then the bow would slap the string harder than she wanted as it engaged the string at a more direct angle. When she engaged the pinky and started to think about the control of the tip, the problem went away instantly.&lt;/p&gt;
&lt;p&gt;While I&amp;rsquo;m not currently practicing &lt;em&gt;spiccato&lt;/em&gt;, Nathan&amp;rsquo;s lesson on pinky engagement illuminates on another problem: shaky down bow.&lt;/p&gt;
&lt;p&gt;There are two common schools of thought about bow change: the most popular paintbrush method, which encourages a soft, flexible wrist as if painting a wall with a brush (demonstrated &lt;a href=&#34;https://www.youtube.com/watch?v=UmDEl-Rasj0&#34;&gt;here&lt;/a&gt;); and the method that supposedly belongs to Nathan Milstein: &amp;ldquo;I move it in one direction, and then I move it back in the opposite direction&amp;rdquo; &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;. I was taught the former, and to be honest, I&amp;rsquo;ve rarely seen anyone who actually make that Milstein method work, other than Milstein himself. The vast majority of violinists do flex their hand and wrist at the frog, some more conspicuous, some subtle, but hardly as quiet as Milstein.&lt;/p&gt;
&lt;p&gt;On the other hand, the paintbrush metaphor is not a perfect one. The emphasis on flexibility in the wrist gives me the impression that bow change is a wrist-centric action. The wrist makes a flexing move, and the rest of the hand just go with the flow. Whenever my bow bounced, I thought to myself that it must be my wrist movement not being fluid enough. And I had never managed to fully fix the problem.&lt;/p&gt;
&lt;p&gt;When I was watching Nathan demonstrating that falling &lt;em&gt;spiccato&lt;/em&gt; with a straight bow, something clicked in my mind. My problem was not with the wrist, but the fingers. Too much flex in the fingers means that they no longer exerts the same amount of the force to the bow stick, so the frog is a little lighter, while unrelenting gravity keeps a constant pull at the center of mass, rotating the bow like a slight nodding. When the bow nods, the tip is lower and the frog is higher, so for a brief moment, the bow is doing exactly the same thing as the student&amp;rsquo;s &lt;em&gt;spiccato&lt;/em&gt; landing. Sort of like a tiny flap of a wave hitting the rock, and bouncing off into the air. That extra upward force propagates through the stick, causing the infamous down bow bounce.&lt;/p&gt;
&lt;p&gt;By engaging the pinky&amp;mdash;more concretely, exerting the pinky to resist the frog from rising&amp;mdash;the bow can be kept straight. It&amp;rsquo;s a somewhat paradoxical sensation: from a physical point of view, we want the force to be constant. But because the natural tendency is to soften the finger together with the wrist, my subjective experience is that the pinky needs to be proactive in that split second, to keep the bow straight. Our perception of force and movement don&amp;rsquo;t always match reality, so to achieve a desired result, sometimes we have to change our perspective and &amp;ldquo;cheat&amp;rdquo; our brain. Choosing the right perspective and the right metaphor is the magic ingredient of a great teacher.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://www.violinist.com/discussion/archive/23953/&#34;&gt;https://www.violinist.com/discussion/archive/23953/&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">A few fun discoveries about Stable Diffusion</title>
    <link rel="alternate">https://powersnail.com/2022/stable-diffusion-fun/</link>
    <published>Thu, 10 Nov 2022 00:00:00 +0000</published>
    <updated>Thu, 10 Nov 2022 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2022/stable-diffusion-fun/</id>
    <summary type="html">Standing opposed to OpenAI&amp;rsquo;s DALL-E and Midjourney, is the open sourced model Stable Diffusion1. Some of the images it painted are genuinely impressive, coherent, and free of artifacts (at least at first glance).</summary>
    <content type="html">&lt;p&gt;Standing opposed to OpenAI&amp;rsquo;s DALL-E and Midjourney, is the open sourced model Stable Diffusion&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;. Some of the images it painted are genuinely impressive, coherent, and free of artifacts (at least at first glance). But those are almost always the result of prompt engineering: an Edisonian process of random search through the infinite linguistic space. Or in other words, people trying different words until they get a desirable result.&lt;/p&gt;
&lt;p&gt;For instance, there&amp;rsquo;s a collection of &amp;ldquo;magic words&amp;rdquo; that improves the quality of the model&amp;rsquo;s output: &amp;ldquo;4k&amp;rdquo;, &amp;ldquo;detailed&amp;rdquo;, etc.&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt; The model associates these key words with the high quality images in its training set, because that&amp;rsquo;s how people label their own work, and thus tries to be close to those images.&lt;/p&gt;
&lt;p&gt;What happens if you don&amp;rsquo;t give it a particularly graphic sentence? How does it deal with the abstract, the metaphysical, and the poetic?&lt;/p&gt;
&lt;h2 id=&#34;literatures-quotes-and-illustrations&#34;&gt;
  Literatures, Quotes, and Illustrations
  &lt;a href=&#34;#literatures-quotes-and-illustrations&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;It gives you the quote right back:&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2022/stable-diffusion-fun/quote-1.webp&#34; alt=&#34;Generated image from Oscar Wilde&amp;amp;rsquo;s quote&#34;srcset=&#34;https://powersnail.com/2022/stable-diffusion-fun/quote-1-400w.webp 400w,/2022/stable-diffusion-fun/quote-1-600w.webp 600w,/2022/stable-diffusion-fun/quote-1-800w.webp 800w,/2022/stable-diffusion-fun/quote-1-1000w.webp 1000w,/2022/stable-diffusion-fun/quote-1-1200w.webp 1200w,/2022/stable-diffusion-fun/quote-1.webp 2560w&#34; width=&#34;2560&#34;  height=&#34;512&#34; &gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Questions are never indiscreet; answers sometimes are.&lt;/p&gt;
&lt;p&gt;&amp;ndash;Oscar Wilde&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;&amp;hellip;&amp;hellip;Not quite verbatim, but close enough. Similar to how &amp;ldquo;4k&amp;rdquo; nudges the model towards higher quality, if you sound like Brainy Quotes, it will paint like Brainy Quotes for you.&lt;/p&gt;
&lt;p&gt;Sometimes, it will go a different route, and illustrate like a book of classics:&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2022/stable-diffusion-fun/quote-2.webp&#34; alt=&#34;Generated image from Oscar Wilde Quote&#34;srcset=&#34;https://powersnail.com/2022/stable-diffusion-fun/quote-2-400w.webp 400w,/2022/stable-diffusion-fun/quote-2-600w.webp 600w,/2022/stable-diffusion-fun/quote-2-800w.webp 800w,/2022/stable-diffusion-fun/quote-2-1000w.webp 1000w,/2022/stable-diffusion-fun/quote-2.webp 1024w&#34; width=&#34;1024&#34;  height=&#34;512&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;If the lower classes don&amp;rsquo;t set us a good example what on earth is the use of them? They seem, as a class, to have absolutely no sense of moral responsibility.&lt;/p&gt;
&lt;p&gt;&amp;ndash;Oscar Wilde&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Now, this is just a silly experimentation. The model is trained on descriptions of images. It&amp;rsquo;s not surprising that it wouldn&amp;rsquo;t do well on metaphysical epigrams depicting no concrete objects. In fact, if you give me drawing prompt &amp;ldquo;Questions are never indiscreet; answers sometimes are&amp;rdquo;, I&amp;rsquo;d probably ask you clarify just what the hell you want me to draw.&lt;/p&gt;
&lt;h2 id=&#34;where-is-the-cicada&#34;&gt;
  Where is the cicada?
  &lt;a href=&#34;#where-is-the-cicada&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2022/stable-diffusion-fun/cicada.webp&#34; alt=&#34;Generated image from a quote taken from Pale Fire&#34;srcset=&#34;https://powersnail.com/2022/stable-diffusion-fun/cicada-400w.webp 400w,/2022/stable-diffusion-fun/cicada-600w.webp 600w,/2022/stable-diffusion-fun/cicada-800w.webp 800w,/2022/stable-diffusion-fun/cicada-1000w.webp 1000w,/2022/stable-diffusion-fun/cicada-1200w.webp 1200w,/2022/stable-diffusion-fun/cicada.webp 2560w&#34; width=&#34;2560&#34;  height=&#34;512&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Waxwings are berry-pecking / a cicada sings.&lt;/p&gt;
&lt;p&gt;&amp;ndash;Nabokov, &lt;em&gt;Pale Fire&lt;/em&gt;&lt;sup id=&#34;fnref:5&#34;&gt;&lt;a href=&#34;#fn:5&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Another limitation I found is that Stable Diffusion sometimes ignores parts of the prompt. This is quite interesting because it obviously is capable of juxtaposing unrelated elements together, as demonstrated by the famous example of an astronaut riding a horse, in its &lt;a href=&#34;https://github.com/CompVis/stable-diffusion&#34;&gt;repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A beautiful line of poetry, &amp;ldquo;Waxwings are berry-pecking / a cicada sings&amp;rdquo;, is not as abstract as the previous section. It depicts two subjects, a bird and a bug, and yet Stable Diffusion absolutely refuses to recognize the existence of the latter.&lt;/p&gt;
&lt;p&gt;Could it be the position of the two words in the sentence? Let&amp;rsquo;s try reversing it:&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2022/stable-diffusion-fun/cicada-reverse.webp&#34; alt=&#34;Generated image from reversing a quote taken from Pale Fire&amp;amp;quot;&#34;srcset=&#34;https://powersnail.com/2022/stable-diffusion-fun/cicada-reverse-400w.webp 400w,/2022/stable-diffusion-fun/cicada-reverse-600w.webp 600w,/2022/stable-diffusion-fun/cicada-reverse-800w.webp 800w,/2022/stable-diffusion-fun/cicada-reverse-1000w.webp 1000w,/2022/stable-diffusion-fun/cicada-reverse-1200w.webp 1200w,/2022/stable-diffusion-fun/cicada-reverse.webp 2560w&#34; width=&#34;2560&#34;  height=&#34;512&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;A cicada sings / Waxwings are berry-pecking.&lt;/p&gt;
&lt;p&gt;Nope. Only the bird itself. Beautifully drawn, but missing its companion.&lt;/p&gt;
&lt;p&gt;Maybe it&amp;rsquo;s the realistic style which it&amp;rsquo;s going for? Let&amp;rsquo;s try adding some stylistic modifiers to the prompt:&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2022/stable-diffusion-fun/cicada-illustration.webp&#34; alt=&#34;Added illustration to the prompt.&amp;amp;quot;&#34;srcset=&#34;https://powersnail.com/2022/stable-diffusion-fun/cicada-illustration-400w.webp 400w,/2022/stable-diffusion-fun/cicada-illustration-600w.webp 600w,/2022/stable-diffusion-fun/cicada-illustration-800w.webp 800w,/2022/stable-diffusion-fun/cicada-illustration-1000w.webp 1000w,/2022/stable-diffusion-fun/cicada-illustration-1200w.webp 1200w,/2022/stable-diffusion-fun/cicada-illustration.webp 2560w&#34; width=&#34;2560&#34;  height=&#34;512&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Waxwings are berry-pecking / a cicada sings. Illustration.&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2022/stable-diffusion-fun/cicada-oil.webp&#34; alt=&#34;Added oil painting to the prompt.&amp;amp;quot;&#34;srcset=&#34;https://powersnail.com/2022/stable-diffusion-fun/cicada-oil-400w.webp 400w,/2022/stable-diffusion-fun/cicada-oil-600w.webp 600w,/2022/stable-diffusion-fun/cicada-oil-800w.webp 800w,/2022/stable-diffusion-fun/cicada-oil-1000w.webp 1000w,/2022/stable-diffusion-fun/cicada-oil-1200w.webp 1200w,/2022/stable-diffusion-fun/cicada-oil.webp 2560w&#34; width=&#34;2560&#34;  height=&#34;512&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Waxwings are berry-pecking / a cicada sings. Oil painting.&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2022/stable-diffusion-fun/cicada-photo.webp&#34; alt=&#34;Added photo to the prompt.&amp;amp;quot;&#34;srcset=&#34;https://powersnail.com/2022/stable-diffusion-fun/cicada-photo-400w.webp 400w,/2022/stable-diffusion-fun/cicada-photo-600w.webp 600w,/2022/stable-diffusion-fun/cicada-photo-800w.webp 800w,/2022/stable-diffusion-fun/cicada-photo-1000w.webp 1000w,/2022/stable-diffusion-fun/cicada-photo-1200w.webp 1200w,/2022/stable-diffusion-fun/cicada-photo.webp 2560w&#34; width=&#34;2560&#34;  height=&#34;512&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Waxwings are berry-pecking / a cicada sings. Photo.&lt;/p&gt;
&lt;p&gt;Still, the cicada is nowhere to be found. And if you look carefully, you&amp;rsquo;ll notice that even &amp;ldquo;berry&amp;rdquo; isn&amp;rsquo;t always there. The model concentrates on &amp;ldquo;waxwings&amp;rdquo;, and that&amp;rsquo;s the only thing it seems to &lt;em&gt;care&lt;/em&gt; about, if you&amp;rsquo;ll excuse the inaccurately personified verb. Perhaps the model has a bias in its training set, some objects being more likely to appear than others, and thus carrying a heavier weight. An image with waxwings, berries, and a cicada is less likely than an image with just a waxwing, even given a prompt that includes all three elements. Is this a fundamental limitation on the model, or is it a deficiency in the training data?&lt;/p&gt;
&lt;h2 id=&#34;last-word&#34;&gt;
  Last word
  &lt;a href=&#34;#last-word&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Stable Diffusion, like many other machine learning models dabbling in art, astonishes the programmer part of my brain. It&amp;rsquo;s utterly ridiculous that we can prompt the program to generate coherent images, without hard-coding any rule about what it means for an image to be coherent. We give zero &lt;em&gt;a priori&lt;/em&gt; to the model on what constitutes a photo or an oil painting, or the anatomy of waxwings, or the color of trees and leaves, and yet, it does show a level of understanding of all those concepts. Put aside the thorny question of &amp;ldquo;how do you define &amp;lsquo;understand&amp;rsquo;?&amp;rdquo;, if we merely judge the program by its performance, it is capable of generating images where a human would recognize the objects, styles, lighting conditions, etc. to be the same as what the prompt describes. And again, without codifying such objects or styles by a human.&lt;/p&gt;
&lt;p&gt;But at the same time, the other parts of my brain still smirks a bit at the results. When you jump even slightly out of the box, Stable Diffusion starts to show its limits. And even within the box, it takes a lot of word tweaking and cherry-picking to get some useful images out of the model. A lot of hobbyists left the model to run overnight on a long list of prompts. In other areas, the music generated by machine learnings are still quite bad, and seems to go from nowhere to nowhere, if we judge the music entirely on its own merit. The same goes for text generation.&lt;/p&gt;
&lt;p&gt;It is quite disquieting to see just how close we are to computer programs surpassing human in the field of creative arts, and perhaps even programming itself. We are not there yet, but I&amp;rsquo;m willing to bet that it&amp;rsquo;s going to happen within the lifetime of my generation. Where would that leave us? To become the Olympians of the machines and reap the fruit of their labor? Or to compete with the machines, and eventually&amp;mdash;inevitably&amp;mdash;become obsolete? Will the society become more equal as the rising productivity and efficiency alleviate scarcity, or will the divide deepen between the wealthy and powerful, and the underprivileged?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Anybody that competes with slaves becomes a slave&lt;/p&gt;
&lt;p&gt;&amp;ndash;Vonnegut, &lt;em&gt;Player Piano&lt;/em&gt;&lt;sup id=&#34;fnref:6&#34;&gt;&lt;a href=&#34;#fn:6&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;6&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2022/stable-diffusion-fun/robot-playing-the-piano.webp&#34; alt=&#34;Image generated from the prompt: A robot playing the piano, 4k, detailed, by Studio Ghibli&#34;srcset=&#34;https://powersnail.com/2022/stable-diffusion-fun/robot-playing-the-piano-400w.webp 400w,/2022/stable-diffusion-fun/robot-playing-the-piano.webp 600w&#34; width=&#34;600&#34;  height=&#34;400&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Generated by Stable Diffusion: A robot playing the piano, 4k, detailed, by Studio Ghibli&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;Rombach, R., Blattmann, A., Lorenz, D., Esser, P., &amp;amp; Ommer, B. (2021). &lt;em&gt;High-resolution image synthesis with latent diffusion models&lt;/em&gt;.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;&lt;em&gt;Stable Diffusion Prompt Book—OpenArt&lt;/em&gt;. (n.d.). OpenArt. Retrieved November 10, 2022, from &lt;a href=&#34;https://openart.ai/&#34;&gt;https://openart.ai/&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;Wilde, O. (2001). &lt;em&gt;An Ideal Husband&lt;/em&gt;. Courier Corporation.&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34;&gt;
&lt;p&gt;Wilde, O. (2017). &lt;em&gt;The Importance of Being Earnest &amp;amp; Other Plays&lt;/em&gt;. Pan Macmillan.&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:5&#34;&gt;
&lt;p&gt;Nabokov, V. (1992). &lt;em&gt;Pale Fire: Introduction by Richard Rorty&lt;/em&gt;. Knopf Doubleday Publishing Group.&amp;#160;&lt;a href=&#34;#fnref:5&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:6&#34;&gt;
&lt;p&gt;Vonnegut, K. (1999). &lt;em&gt;Player Piano&lt;/em&gt;. Random House Publishing Group.&amp;#160;&lt;a href=&#34;#fnref:6&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">Fixing Grub2 Theme Preview on Opensuse Tumbleweed</title>
    <link rel="alternate">https://powersnail.com/2022/grub2-theme-preview-opensuse/</link>
    <published>Sat, 06 Aug 2022 00:00:00 +0000</published>
    <updated>Sat, 06 Aug 2022 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2022/grub2-theme-preview-opensuse/</id>
    <summary type="html">To use Grub2 theme preview on openSUSE, two environment variables needs to be overridden.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;TLDR&lt;/strong&gt;: To use &lt;a href=&#34;https://github.com/hartwork/grub2-theme-preview&#34;&gt;grub2-theme-preview&lt;/a&gt; on openSUSE, you need to override the paths of firmware and ovmf:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;G2TP_GRUB_LIB&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/usr/share/grub2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;G2TP_OVMF_IMAGE&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/usr/share/qemu/ovmf-x86_64-code.bin&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;p&gt;Running after installing grub2-theme-preview and it&amp;rsquo;s dependencies on openSUSE Tumbleweed, I was given the following error:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;gt; grub2-theme-preview .
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ERROR: &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;Errno 2&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; GRUB platform directory &lt;span class=&#34;s2&#34;&gt;&amp;#34;/usr/lib/grub/x86_64-efi&amp;#34;&lt;/span&gt; not found&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is because grub2-theme-preview hard codes a few paths for this file, which unfortunately do not include openSUSE&amp;rsquo;s layout.&lt;/p&gt;
&lt;p&gt;The path can be overridden with undocumented an environment variables, which isn&amp;rsquo;t mentioned in the help message or REAME.md, but it can be seen in code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# __main__.py&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;_grub2_directory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;platform&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;environ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;G2TP_GRUB_LIB&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;/usr/lib/grub&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;platform&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Where is it in openSUSE? The error message says that &amp;ldquo;/usr/lib/grub/x86_64-efi&amp;rdquo; was not found, so let&amp;rsquo;s find x86-64-efi:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;gt;  fd x86_64-efi /usr
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/usr/share/grub2/x86_64-efi/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The code tells us that &lt;code&gt;G2TP_GRUB_LIB&lt;/code&gt; should refer to the directory that contains &lt;code&gt;x86_64-efi&lt;/code&gt;, so we can override the environment variable:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;G2TP_GRUB_LIB&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/usr/share/grub2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, let&amp;rsquo;s run it again:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;gt; grub2-theme-preview .
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ERROR: &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;Errno 2&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; OVMF image file &lt;span class=&#34;s2&#34;&gt;&amp;#34;/usr/share/[..]/OVMF_CODE.fd&amp;#34;&lt;/span&gt; is missing, please install package &lt;span class=&#34;s1&#34;&gt;&amp;#39;edk2-ovmf&amp;#39;&lt;/span&gt; or &lt;span class=&#34;s1&#34;&gt;&amp;#39;ovmf&amp;#39;&lt;/span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Okay, so there&amp;rsquo;s another one. Again, digging into the code, we can find another environment variable:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;_grub2_ovmf_tuple&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;omvf_image&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;environ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;G2TP_OVMF_IMAGE&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;omvf_image&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# Support non-standard locations e.g. NixOS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;candidates&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;omvf_image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;candidates&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;s1&#34;&gt;&amp;#39;/usr/share/edk2-ovmf/OVMF_CODE.fd&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# Gentoo and its derivatives&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;s1&#34;&gt;&amp;#39;/usr/share/edk2-ovmf/x64/OVMF_CODE.fd&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# Arch Linux and its derivatives&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;s1&#34;&gt;&amp;#39;/usr/share/OVMF/OVMF_CODE.fd&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# Debian and its derivatives&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;s1&#34;&gt;&amp;#39;/usr/share/edk2/ovmf/OVMF_CODE.fd&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# Fedora (and its derivatives?)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;OVMF_CODE.fd&lt;/code&gt;, however, is more elusive. &lt;code&gt;fd OVMF_CODE&lt;/code&gt; returns nothing. After some Googling and forum digging, it turns out that openSUSE does not name the UEFI firmware as &lt;code&gt;OVMF_CODE.fd&lt;/code&gt;; rather, &lt;code&gt;ovmf-[arch]-code.bin&lt;/code&gt;. For my purpose, the x86_64 version is located at &lt;code&gt;/usr/share/qemu/ovmf-x86_64-code.bin&lt;/code&gt;. This time, &lt;code&gt;grub2-theme-preview&lt;/code&gt; is looking for the path of the file, rather than the directory, so, we set the environment variable:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;G2TP_OVMF_IMAGE&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/usr/share/qemu/ovmf-x86_64-code.bin&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Running &lt;code&gt;grub2-theme-preview&lt;/code&gt; once again:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;gt; grub2-theme-preview .
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;INFO: Appending to fonts to load: ascii.pf2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;INFO: Appending to fonts to load: DejaVuSans-Bold14.pf2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;INFO: Appending to fonts to load: DejaVuSans10.pf2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;INFO: Appending to fonts to load: DejaVuSans12.pf2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;INFO: Found OVMF image at &lt;span class=&#34;s1&#34;&gt;&amp;#39;/usr/share/qemu/ovmf-x86_64-code.bin&amp;#39;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;INFO: Please give GRUB a moment to show up in QEMU...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;Voila!&lt;/em&gt;&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/images/opensuse-grub-preview.webp&#34; alt=&#34;Screenshot of grub2-theme-preview&#34;srcset=&#34;https://powersnail.com/images/opensuse-grub-preview-400w.webp 400w,/images/opensuse-grub-preview-600w.webp 600w,/images/opensuse-grub-preview-800w.webp 800w,/images/opensuse-grub-preview-1000w.webp 1000w,/images/opensuse-grub-preview.webp 1200w&#34; width=&#34;1200&#34;  height=&#34;675&#34; &gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">Making &lt;em&gt;Score In URL&lt;/em&gt;</title>
    <link rel="alternate">https://powersnail.com/2022/score-in-url/</link>
    <published>Fri, 29 Jul 2022 00:00:00 +0000</published>
    <updated>Fri, 29 Jul 2022 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2022/score-in-url/</id>
    <summary type="html">I&amp;rsquo;m excited to publish my new project, Score In URL, a simple, privacy-friendly, sheet music sharing service, where the entire content is encoded in the URL itself as a query parameter.</summary>
    <content type="html">&lt;p&gt;I&amp;rsquo;m excited to publish my new project, &lt;a href=&#34;https://powersnail.com/ScoreInUrl&#34;&gt;Score In URL&lt;/a&gt;, a simple, privacy-friendly, sheet music sharing service, where the entire content is encoded in the URL itself as a query parameter. It comes with a decent editor, the score, and the audio.&lt;/p&gt;
&lt;h2 id=&#34;an-easy-way-to-share-musical-scores&#34;&gt;
  An easy way to share musical scores
  &lt;a href=&#34;#an-easy-way-to-share-musical-scores&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The inspiration came to me when I was trying to share a little snippet of music on a forum. It was just a short exercise, but I wanted to deliver both the sheet music and the audio. Most forums don&amp;rsquo;t natively support sharing any form of sheet music notation, apart from just using an image. But to open up a composing program, export to an image, upload that image to Imgur, and finally share that link just for a one-line snippet, it&amp;rsquo;s tedious, and it&amp;rsquo;s an overkill. More importantly, an image has no sound. For that, there are more hoops to jump through.&lt;/p&gt;
&lt;p&gt;I already knew that abcjs has an editor in browser that can play audio, so what I did was asking them to go to &lt;a href=&#34;https://www.abcjs.net/abcjs-editor.html&#34;&gt;the abcjs editor&lt;/a&gt;, and then, copy &amp;amp; paste my snippet in there. It works; there&amp;rsquo;s image and there&amp;rsquo;s sound, but it&amp;rsquo;s kinda awkward that they have to manually fill in the score, rather than opening a link with the right content already there.&lt;/p&gt;
&lt;p&gt;Something came to my mind: &lt;a href=&#34;https://hashify.me/&#34;&gt;hashify&lt;/a&gt; is a website which encodes a Markdown document in its URL. Pretty brilliant idea.&lt;/p&gt;
&lt;p&gt;So, I decided to build something similar for ABC Notation. It allows you to enter plain text music just like &lt;em&gt;abcjs editor&lt;/em&gt;, while the whole text is encoded into the URL, just like &lt;em&gt;hashify&lt;/em&gt;. All you need to do is copy the URL to your friend, and they get the source, the sheet music, and audio in a single click. It doesn&amp;rsquo;t get any simpler than that.&lt;/p&gt;
&lt;h2 id=&#34;static-server-less-privacy-friendly&#34;&gt;
  Static, server-less, privacy-friendly
  &lt;a href=&#34;#static-server-less-privacy-friendly&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Since there&amp;rsquo;s no need to store any file, the project can be entirely server-less. All it takes is a base64 decoder and abcjs, which can all be done in the frontend. This is why I&amp;rsquo;ve decided to use the query parameter, eliminating the need for server-side routing. The page takes a single parameter &lt;code&gt;s&lt;/code&gt;, which contains the encoded score.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ts&#34; data-lang=&#34;ts&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;decodeScore&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;params&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;URLSearchParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;location&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;search&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;encoded&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;kr&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;s&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;encoded&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;null&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;try&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;atob&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;encoded&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;catch&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nx&#34;&gt;alert&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;URL not valid. Showing default score...&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;DEFAULT_SCORE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;encodeScore&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;content&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;encoded&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;btoa&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;url&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;URL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;document&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;location&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;href&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;searchParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;kr&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;s&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;encoded&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;toString&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The code for &lt;em&gt;Score In URL&lt;/em&gt; is &lt;a href=&#34;https://github.com/PowerSnail/ScoreInUrl&#34;&gt;here&lt;/a&gt;. Bundled by [vite.js], everything compiles down to a pair of HTML and JS file. No backend, no cookies, no tracking, no storage. It lives entirely inside that one browser tab.&lt;/p&gt;
&lt;p&gt;This approach has its own caveat: size limit. URLs are traditionally at most 2048 characters. How many pages of sheet music you get from those 2048 characters depend on your score, but the spirit of &lt;strong&gt;Score In URL&lt;/strong&gt; is to share short snippets of sheet music, not to be a full-fledged music editor. There are much better tools out there for composing.&lt;/p&gt;
&lt;h2 id=&#34;abc-notation-and-abcjs&#34;&gt;
  ABC Notation and abcjs
  &lt;a href=&#34;#abc-notation-and-abcjs&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;ABC Notation is possibly the most hand-writable plain text format for composing sheet music. Most engraving software are WYSIWYG (What You See Is What You Get), which means you are directly interacting with the score, requiring a graphical interface. For a composer sitting in front of their workstation, this is fine, but it&amp;rsquo;s too heavy for building a quick, shareable snippet of music. On the other end of the spectrum, ABC Notation is just plain text. For something simple of a few measures long, it does the job better than any other system.&lt;/p&gt;
&lt;p&gt;Not unlike how people already do in forums, you simply write out the note names: &lt;code&gt;CDEFGAB&lt;/code&gt;. Capital letters denote the range from &lt;code&gt;C4~B4&lt;/code&gt;, lower case letters give you an octave higher, and to get more than that range, put a &lt;code&gt;&#39;&lt;/code&gt; after the note to raise an octave, and a &lt;code&gt;_&lt;/code&gt; to lower one. Note length is simple math: you define a unit length in the beginning, for instance, with &lt;code&gt;L: 1/16&lt;/code&gt;, &lt;code&gt;C&lt;/code&gt; is a 16th note, &lt;code&gt;C2&lt;/code&gt; is an 8th note, &lt;code&gt;C/2&lt;/code&gt; is a 32nd note, and &lt;code&gt;C3/2&lt;/code&gt; is a dotted 16th note.&lt;/p&gt;
&lt;p&gt;To write a simple C Major scale:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;T: C Major Scale
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;L: 1/16
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;M: 2/4
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;C2DE FGAB | c2de fgab | c&amp;#39;2ba gfed | c2BA GFED | C8&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The result looks like:&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2022/score-in-url/c_maj.webp&#34; alt=&#34;The rendered score of C Major Scale&#34;srcset=&#34;https://powersnail.com/2022/score-in-url/c_maj-400w.webp 400w,/2022/score-in-url/c_maj-600w.webp 600w,/2022/score-in-url/c_maj-800w.webp 800w,/2022/score-in-url/c_maj-1000w.webp 1000w,/2022/score-in-url/c_maj.webp 1200w&#34; width=&#34;1200&#34;  height=&#34;230&#34; &gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;You can visit &lt;a href=&#34;https://powersnail.com/ScoreInUrl/?s=VDogQyBNYWpvciBTY2FsZQpMOiAxLzE2Ck06IDIvNApDMkRFIEZHQUIgfCBjMmRlIGZnYWIgfCBjJzJiYSBnZmVkIHwgYzJCQSBHRkVEIHwgQzg%3D&#34;&gt;this link&lt;/a&gt; to see and hear the C Major scale on &lt;strong&gt;Score In URL&lt;/strong&gt;. Or a number of other examples: &lt;a href=&#34;https://powersnail.com/ScoreInUrl/?s=VDogUGFydGl0YSBJSUkgLSBQcmVsdWRpbwpDOiBKLlMuIEJhY2gKUTogMS80PTEyMApNOiAzLzQKTDogMS8xNgpLOiBFbWFqCnoyIGUnZCcgZScyYjJnMmIyIHwgKGVmZWQgZTIpQjJHMkIyIHwgRUJGQiBHQkFCIEdCRkIgfApFZWRjIEJlZGMgQkFHRiAgICB8IEVCRkIgR0JBQiBHQkZCICB8IEVlZGMgQmVkYyBCQUdGIHwKRUZHQSBCY2RlIGZnYWYgICAgfCBnYmVmIGdhYmMnIGQnZSdjJ2QnICB8IGUnYmFiIGdiYWIgZ2JmYiB8CmVlJ2QnYycgYmVjJ2UgYmVhZXwgZ2JmYiBnYmFiIGdiZmIgIHwgZWUnZCdjJyBiZWMnZSBiZWFlIHwKZ2VlZWRlZWVmZWRlIHwgZWVnZWZlZ2VhZWZlIHwgZ2VlZWRlZWVmZWRlIHwKZWVnZWZlZ2VhZWZlIHwgZ2VnZSBnZWdlIGdlZ2UgfCBnZWdkIGdlZ2QgZ2VnZCB8CmdlZz1kIGdlZ2QgZ2VnZCB8IGFlYWMgYWVhYyBhZWFjIHwgYWVhQiBhZWFCIGFlYUIgfApnZWdCIGdlZ0IgZ2VnQiB8IGdlZ0EgZ2VnQSBnZWdBIHwgZmVmQSBmZWZBIGZlZkEgfApmZWZHIGZlZkcgZmVmRyB8IGVlZUcgZWVlRyBlZWVHIHwgZWVlRiBlZWVGIGVlZUYgfApkZWRGIGRlZEYgZGVkRiB8IEVGRUYgR0JFRiBHQkVGIHwgR0FHQSBCZUdBIEJlR0EgfA%3D%3D&#34;&gt;First page of Bach&amp;rsquo;s Preludio&lt;/a&gt;, &lt;a href=&#34;https://powersnail.com/ScoreInUrl/?s=VDogQWlyIG9uIEcgU3RyaW5nCkM6IEouUy4gQmFjaCAoYXJyLiBBdWd1c3QgV2lsaGVsbWouKQpROiAiTGVudG8iCk06IDQvNApMOiAxLzE2Cks6IENtYWoKfDogRTE2LSB8IEUyKEFGIERDQixDKSAoIXRyaWxsIUIsNy8yQSwvMikgRyw0IHwgRzgtIEcoRV9CLEEsKSAoRF5DKShHRikgfCAKRjgtIEYoREEsRywpIChDQiwpKEZFKSB8IChFNiBeRkcpIChDMkMvMkQvMkUpIChFRCkoREMpIHwgKEIsQSwpKEEsLzJCLC8yQykgKEMyQixBLCkgRyw4IDp8IAp8OiAoQiw0LUIsQy8yQiwvMkEsLzJCLC8yRywpIChHNiBfQiwyKSB8IChBLDJBMi0gQSkoR0ZFKSB7L0V9RjQtIEYvMihFLzJELzJDLzJCLEEsKSB8IF5HLEEsKEIsMi0gQixDKShEMi0gREUpRjItIEYyRTIgfAooREMpKEIsQSwpIChCLEMvMkQvMkNCLCkgQSw4IHwgKEM0LSBDRURDKSAoQTYgR15GKSB8ICh7L0V9REdHLDIpIChBLDNCLC8yQy8yKSAoQiw3LzJBLC8yKSBHLDQgfCAKQzYgKEVEKSBENiAoRkUpIHwgRTYgKEdGKSBGOCB8IEcsNC0gRyxCLERGIEZERTItIEUyKEVGLzJHLzIpIHwgCihDNC0gQ0VHX0IpIChCMiBBNCBDMikgfCAoQixEIEY0IEEsMikgKEcsMkRFLzJGLzItIEYpKEUyRCB8IEMvMkIsLzIpKEEsMkIsKSAoQiwyey9BLH1CLEMpIEM4IDp8Cg%3D%3D&#34;&gt;Air on G String&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To learn more about writing ABC notation, visit their &lt;a href=&#34;https://abcnotation.com/&#34;&gt;official website&lt;/a&gt;. There are plenty of examples and an exhaustive documentation. For quick references, this &lt;a href=&#34;http://www.stephenmerrony.co.uk/uploads/ABCquickRefv0_6.pdf&#34;&gt;cheat sheet&lt;/a&gt; is superb.&lt;/p&gt;
&lt;p&gt;Thanks to &lt;a href=&#34;https://www.abcjs.net/&#34;&gt;abcjs&lt;/a&gt;, it&amp;rsquo;s super easy to embed such a system in a web page. Abcjs provides rendering, audio, and error messages which integrate nicely with CodeMirror, the text editor.&lt;/p&gt;
&lt;h2 id=&#34;text-editing&#34;&gt;
  Text Editing
  &lt;a href=&#34;#text-editing&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;To provide some rudimentary code highlighting, and more importantly, ergonomic error reporting, &lt;a href=&#34;https://codemirror.net/&#34;&gt;CodeMirror&lt;/a&gt; is used. You can see the errors marked by red dots, like a real text editor used by programmers.&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2022/score-in-url/Screenshot_error.webp&#34; alt=&#34;Screenshot showcasing error reporting&#34;srcset=&#34;https://powersnail.com/2022/score-in-url/Screenshot_error-400w.webp 400w,/2022/score-in-url/Screenshot_error-600w.webp 600w,/2022/score-in-url/Screenshot_error-800w.webp 800w,/2022/score-in-url/Screenshot_error-1000w.webp 1000w,/2022/score-in-url/Screenshot_error-1200w.webp 1200w,/2022/score-in-url/Screenshot_error.webp 1702w&#34; width=&#34;1702&#34;  height=&#34;346&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;The code highlighting is still not comprehensive at the moment. I&amp;rsquo;ve merely written a few tokenization rules at this point, and certainly will improve on that in the future.&lt;/p&gt;
&lt;h2 id=&#34;not-in-the-scope&#34;&gt;
  Not in the scope
  &lt;a href=&#34;#not-in-the-scope&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve decided against using a compression algorithm. A simple base64 encoder is available everywhere, whereas compression requires a 3rd party library, and might be subject to the specific quirks of that implementation. If the compression has a bug, it infects every URL shared from &lt;strong&gt;Score In URL&lt;/strong&gt;. If that algorithm ever gets an update that is not backwards-compatible, all the old URLs are screwed. Furthermore, if &lt;strong&gt;Score In URL&lt;/strong&gt; disappears, a plain base64 string is simple to use: just copy &amp;amp; paste into any base64 decoder. It requires no programming skill, no tool chains, no setup. On the other hand, a compressed string is much harder to decode, especially if the user has no convenient way of installing the exact version of the compression algorithm I used.&lt;/p&gt;
&lt;p&gt;Despite the existence of a &amp;ldquo;Print&amp;rdquo; button, printing likely won&amp;rsquo;t be perfect, especially if you have more than one page of scores. Again, the project is meant for sharing snippets of music, not for typesetting a multipage score. The whole thing is rendered on to a single image, and as long as that image looks alright in the browser, that&amp;rsquo;s all it matters to me.&lt;/p&gt;
&lt;h2 id=&#34;to-do&#34;&gt;
  To Do
  &lt;a href=&#34;#to-do&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;There are a few improvements on my mind.&lt;/p&gt;
&lt;p&gt;First, the code highlighting should be improved. I should at least tokenize all the operators.&lt;/p&gt;
&lt;p&gt;Second, there should be a synchronized cursor between the code editor and the score. In other words, when you are editing the plain text file, you should be able to see where you are on the engravings.&lt;/p&gt;
&lt;p&gt;Third, some UI adjustments. I&amp;rsquo;m not satisfied with the way the buttons are laid out. It doesn&amp;rsquo;t feel entirely intuitive, and is certainly something that I&amp;rsquo;ll need some feedback on. There are also some strange bugs with iOS Safari, especially in landscape mode.&lt;/p&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">Sneaky Shift in Bach&amp;rsquo;s &lt;em&gt;Preludio&lt;/em&gt; in Partita III</title>
    <link rel="alternate">https://powersnail.com/2022/bach-preludio-sneaky-shift/</link>
    <published>Fri, 22 Jul 2022 00:00:00 +0000</published>
    <updated>Fri, 22 Jul 2022 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2022/bach-preludio-sneaky-shift/</id>
    <summary type="html">Preludio (Prelude in some version) is one of Bach&amp;rsquo;s best violin pieces. From measure 17 to 28, a bariolage among three strings brings us a sublime polyphonic experience, with only single notes played detaché.</summary>
    <content type="html">&lt;p&gt;&lt;em&gt;Preludio&lt;/em&gt; (&lt;em&gt;Prelude&lt;/em&gt; in some version) is one of Bach&amp;rsquo;s best violin pieces. From measure 17 to 28, a bariolage among three strings brings us a sublime polyphonic experience, with only single notes played detaché. The focus is usually on the bowing, but the left hand is not without challenge either, especially at speed.&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2022/bach-preludio-sneaky-shift/bariolage-full.webp&#34; alt=&#34;Sheet music of the bariolage section&#34;srcset=&#34;https://powersnail.com/2022/bach-preludio-sneaky-shift/bariolage-full-400w.webp 400w,/2022/bach-preludio-sneaky-shift/bariolage-full-600w.webp 600w,/2022/bach-preludio-sneaky-shift/bariolage-full-800w.webp 800w,/2022/bach-preludio-sneaky-shift/bariolage-full-1000w.webp 1000w,/2022/bach-preludio-sneaky-shift/bariolage-full-1200w.webp 1200w,/2022/bach-preludio-sneaky-shift/bariolage-full.webp 1912w&#34; width=&#34;1912&#34;  height=&#34;1156&#34; &gt;

    &lt;figcaption&gt;Snippet from Preludio&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;From measure 20 to 28, the left hand descends one position every two measures. The most straightforward way is to shift at the beginning of measure 21, 23, 25, 27, and 28, using the third finger on A string, the first finger always pressing the lower note on D string, as shown below:&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2022/bach-preludio-sneaky-shift/straightforward-shift.webp&#34; alt=&#34;The straight-forward version&#34;srcset=&#34;https://powersnail.com/2022/bach-preludio-sneaky-shift/straightforward-shift-400w.webp 400w,/2022/bach-preludio-sneaky-shift/straightforward-shift-600w.webp 600w,/2022/bach-preludio-sneaky-shift/straightforward-shift-800w.webp 800w,/2022/bach-preludio-sneaky-shift/straightforward-shift-1000w.webp 1000w,/2022/bach-preludio-sneaky-shift/straightforward-shift-1200w.webp 1200w,/2022/bach-preludio-sneaky-shift/straightforward-shift.webp 2693w&#34; width=&#34;2693&#34;  height=&#34;258&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;There are two ways to hide this shift. The first is to squeeze your 3rd finger inward without shifting when the bow is still on the D string, and then to complete the shift by moving the 1st finger while playing the other three notes. But given how cramped the notes are on higher positions, that squeeze might be a bit awkward.&lt;/p&gt;
&lt;p&gt;The second way is to delay the shift and hide it using the open E. In measure 20, the 1st finger is on C♯, the 2nd finger on A. If we don&amp;rsquo;t shift, we&amp;rsquo;ll begin measure 21 with 2nd finger on A, too. Then, when the bow is on the open E, shift the entire hand down a position, and substitute the 3rd finger on A, the 1st finger naturally falling on B. If you can shift within the duration of that E, there will be no audible shift. And this way, there is no squeezing, or awkward hand frame. Like this:&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2022/bach-preludio-sneaky-shift/sneaky-shift.webp&#34; alt=&#34;The sneaky version&#34;srcset=&#34;https://powersnail.com/2022/bach-preludio-sneaky-shift/sneaky-shift-400w.webp 400w,/2022/bach-preludio-sneaky-shift/sneaky-shift-600w.webp 600w,/2022/bach-preludio-sneaky-shift/sneaky-shift-800w.webp 800w,/2022/bach-preludio-sneaky-shift/sneaky-shift-1000w.webp 1000w,/2022/bach-preludio-sneaky-shift/sneaky-shift-1200w.webp 1200w,/2022/bach-preludio-sneaky-shift/sneaky-shift.webp 2693w&#34; width=&#34;2693&#34;  height=&#34;269&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Then, in the measure 22, no shift is needed. In measure 23, begin with 2nd finger on G♯, shift during the open string E, and end with 3rd finger on G♯. So on, and so on.&lt;/p&gt;
&lt;p&gt;There are many opportunities in this piece to use the sneaky shift. Measure 67 begins a bariolage that exactly mirrors this sections on the lower strings, so does the technique. The two-string bariolages, like the ones from measure 13~16, also have a few places for sneaky shift.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;If you study the fingering of great violinists, you&amp;rsquo;ll see a lot of creativity in how they achieve the balance between techniques, musicality, and ergonomics. Szeryng&amp;rsquo;s fingering of solo Bach is famous for its clever problem-solving skills, using tiny slides to avoid awkward string crossing, using stretches to avoid slides, etc.&lt;/p&gt;
&lt;p&gt;At the end of the day, it all depends on what kind of phrasing and tone you have in mind. A sneaky shift is great for that clean crisp sound, and an over-slide might be just what you need in a lyrical moment. Fingering is personal, because style is personal.&lt;/p&gt;
&lt;h2 id=&#34;reference&#34;&gt;
  Reference
  &lt;a href=&#34;#reference&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Bach, Johann Sebastian. &lt;em&gt;Drei Sonaten Und Drei Partiten Fur Violino Solo&lt;/em&gt;. Bärenreiter Verlag, 1720, &lt;a href=&#34;https://imslp.org/wiki/6_Violin_Sonatas_and_Partitas,_BWV_1001-1006_(Bach,_Johann_Sebastian)&#34;&gt;6 Violin Sonatas and Partitas, BWV 1001-1006 (Bach, Johann Sebastian) - IMSLP: Free Sheet Music PDF Download&lt;/a&gt;.&lt;/p&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">Reading &lt;em&gt;Steal Like an Artist&lt;/em&gt;</title>
    <link rel="alternate">https://powersnail.com/2022/steal-like-an-artist/</link>
    <published>Sun, 17 Jul 2022 00:00:00 +0000</published>
    <updated>Sun, 17 Jul 2022 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2022/steal-like-an-artist/</id>
    <summary type="html">Summary ## A short, inspirational book about how to be a productive artist. The first few chapters are about imitation, the necessity of it, and how to evolve from there.</summary>
    <content type="html">&lt;h2 id=&#34;summary&#34;&gt;
  Summary
  &lt;a href=&#34;#summary&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;A short, inspirational book about how to be a productive artist. The first few chapters are about imitation, the necessity of it, and how to evolve from there. The author talks about graduating from imitating to emulating: from copying what your heroes make, to copying what your heroes see and hear, which is how &amp;ldquo;stealing&amp;rdquo; can be incorporated into the process of making original art.&lt;/p&gt;
&lt;p&gt;Later, the book offers some practical tips on gathering inspirations: &amp;ldquo;use your hand&amp;rdquo;, keep hobbies, share, travel, be nice to people, stay out of fights, have daily, regular routines, and put strategic constraints on yourself.&lt;/p&gt;
&lt;p&gt;An interesting quote:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Complain about the way other people make software by making software.”
—Andre Torrez&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;thoughts&#34;&gt;
  Thoughts
  &lt;a href=&#34;#thoughts&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s always fascinating when artists talking about their own process, the way each artist find their own authenticity, the source of originality. Neil Gaiman talked about confluence. Here, Austin Kleon talks about imitation and graduating from imitation.&lt;/p&gt;
&lt;p&gt;Create what you like. Write the book that you would want to read. Make the software that you&amp;rsquo;d like to use.&lt;/p&gt;
&lt;p&gt;Creating what you like is in itself a form of imitation, since your taste is formed by appreciating existing arts. This warm and inviting advice deviates from the traditional and stern directive that writers sometimes throw about: &amp;ldquo;Write what you know&amp;rdquo;, and I think the deviation is a valuable one.&lt;/p&gt;
&lt;p&gt;There are different interpretations of &amp;ldquo;writing what you know&amp;rdquo;, (some would insist that you should never make things up when you include something from the real world in your fiction), but if you think about it, all we &lt;em&gt;can&lt;/em&gt; write, is what we know. Like J.R.R. Tolkein said, &amp;ldquo;there is no &amp;lsquo;invention&amp;rsquo; in the void&amp;rdquo;. It&amp;rsquo;s not much of a guideline for writers. It&amp;rsquo;s just the nature of our thought process.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s why to &amp;ldquo;create what you like&amp;rdquo; is a better advice. It actually tells you how to narrow down your choice. From the vast gallery of life experiences, pick the ones that you enjoy the most, immerse yourself in it, and make something out of it.&lt;/p&gt;
&lt;h2 id=&#34;reference&#34;&gt;
  Reference
  &lt;a href=&#34;#reference&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Kleon, Austin. &lt;em&gt;Steal like an Artist: 10 Things Nobody Told You about Being Creative&lt;/em&gt;. 2022.&lt;/p&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">Test Md Page</title>
    <link rel="alternate">https://powersnail.com/2022/test-md-page/</link>
    <published>Wed, 06 Jul 2022 00:00:00 +0000</published>
    <updated>Wed, 06 Jul 2022 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2022/test-md-page/</id>
    <summary type="html">When you are tweaking your blog, creating a new CSS rule, or making a new theme, it is not uncommon</summary>
    <content type="html">&lt;p&gt;When you are tweaking your blog, creating a new CSS rule, or making a new theme, it is not uncommon to break pages that you are not looking. Maybe tables lose their responsiveness, sentences are too close together, empty pages look weird, etc. I&amp;rsquo;ve written this document to test some common pitfalls that I experienced when I was tweaking my own blog.&lt;/p&gt;
&lt;h2 id=&#34;this-is-a-second-level-heading&#34;&gt;
  This is a second-level heading
  &lt;a href=&#34;#this-is-a-second-level-heading&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id=&#34;this-is-a-third-level-heading&#34;&gt;
  This is a third-level heading
  &lt;a href=&#34;#this-is-a-third-level-heading&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;h4 id=&#34;this-is-a-fourth-level-heading&#34;&gt;
  This is a fourth-level heading
  &lt;a href=&#34;#this-is-a-fourth-level-heading&#34;&gt;&lt;small&gt;####&lt;/small&gt;&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;A paragraph under a fourth level heading. There&amp;rsquo;s really no need to get to this level of heading, however.&lt;/p&gt;
&lt;h5 id=&#34;this-is-a-fifth-level-heading&#34;&gt;
  This is a fifth-level heading
  &lt;a href=&#34;#this-is-a-fifth-level-heading&#34;&gt;&lt;small&gt;#####&lt;/small&gt;&lt;/a&gt;
&lt;/h5&gt;
&lt;p&gt;A paragraph under a fifth level heading.&lt;/p&gt;
&lt;h6 id=&#34;this-is-a-sixth-level-heading&#34;&gt;
  This is a sixth-level heading
  &lt;a href=&#34;#this-is-a-sixth-level-heading&#34;&gt;&lt;small&gt;######&lt;/small&gt;&lt;/a&gt;
&lt;/h6&gt;
&lt;p&gt;A paragraph under a sixth level heading.&lt;/p&gt;
&lt;h3 id=&#34;a-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-long-heading&#34;&gt;
  A very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long heading
  &lt;a href=&#34;#a-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-long-heading&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;h2 id=&#34;shapes-of-paragraphs&#34;&gt;
  Shapes of paragraphs
  &lt;a href=&#34;#shapes-of-paragraphs&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;This is a long paragraph. (Content from &lt;em&gt;Pride and Prejudice&lt;/em&gt;)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;An invitation to dinner was soon afterwards dispatched; and already had Mrs. Bennet planned the courses that were to do credit to her housekeeping, when an answer arrived which deferred it all. Mr. Bingley was obliged to be in town the following day, and consequently unable to accept the honour of their invitation, etc. Mrs. Bennet was quite disconcerted. She could not imagine what business he could have in town so soon after his arrival in Hertfordshire; and she began to fear that he might be always flying about from one place to another, and never settled at Netherfield as he ought to be. Lady Lucas quieted her fears a little by starting the idea of his being gone to London only to get a large party for the ball; and a report soon followed that Mr. Bingley was to bring twelve ladies and seven gentlemen with him to the assembly. The girls grieved over such a number of ladies; but were comforted the day before the ball by hearing, that instead of twelve, he had brought only six with him from London, his five sisters and a cousin. And when the party entered the assembly room it consisted of only five altogether; Mr. Bingley, his two sisters, the husband of the eldest, and another young man.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;This is a succession of paragraphs that each contains a short sentence, but not with an extra white line. According to convention, they should be rendered as a single paragraph.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A dog is here.
A cat is there.
Look at that.
A spoon drops into the lake.
Ripples radiate to the shore.
The moon wrinkled in the water.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;This is a succession of paragraphs that each contains a short sentence, with an extra line in between.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Twelve o’clock.&lt;/p&gt;
&lt;p&gt;Along the reaches of the street&lt;/p&gt;
&lt;p&gt;Held in a lunar synthesis,&lt;/p&gt;
&lt;p&gt;Whispering lunar incantations&lt;/p&gt;
&lt;p&gt;Disolve the floors of memory&lt;/p&gt;
&lt;p&gt;And all its clear relations,&lt;/p&gt;
&lt;p&gt;Its divisions and precisions,&lt;/p&gt;
&lt;p&gt;Every street lamp that I pass&lt;/p&gt;
&lt;p&gt;Beats like a fatalistic drum,&lt;/p&gt;
&lt;p&gt;And through the spaces of the dark&lt;/p&gt;
&lt;p&gt;Midnight shakes the memory&lt;/p&gt;
&lt;p&gt;As a madman shakes a dead geranium.&lt;/p&gt;
&lt;p&gt;by T.S. Eliot, &lt;em&gt;Rhapsody on a Windy Night&lt;/em&gt;&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&#34;length-of-line&#34;&gt;
  Length of line
  &lt;a href=&#34;#length-of-line&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;One line should contain about 2~3 alphabets&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;p&gt;abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz&lt;mark&gt;abcdefghijklmnopqrstuvwxyz&lt;/mark&gt;&lt;/p&gt;
&lt;h2 id=&#34;punctuations&#34;&gt;
  Punctuations
  &lt;a href=&#34;#punctuations&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Comma, period, question marks and exclamation marks.&lt;/p&gt;
&lt;p&gt;&lt;mark&gt;Is this a question mark? Yes!&lt;/mark&gt;&lt;/p&gt;
&lt;p&gt;Quotation marks should have the correct orientations:&lt;/p&gt;
&lt;p&gt;&lt;mark&gt;&amp;ldquo;Quotations marks &amp;lsquo;rocks&amp;rsquo;&amp;quot;&lt;/mark&gt;&lt;/p&gt;
&lt;p&gt;Colon, and semicolon:&lt;/p&gt;
&lt;p&gt;&lt;mark&gt;Here: a colon; which is nothing like a semicolon.&lt;/mark&gt;&lt;/p&gt;
&lt;p&gt;Ellipses should be rendered as one character, instead of 3 dots.&lt;/p&gt;
&lt;p&gt;&lt;mark&gt;Ellipses&amp;hellip;&lt;/mark&gt;&lt;/p&gt;
&lt;p&gt;Hyphen and dashes. A &lt;strong&gt;hyphen&lt;/strong&gt; is the shortest, an &lt;strong&gt;en dash&lt;/strong&gt; slightly longer, and an &lt;strong&gt;em dash&lt;/strong&gt; twice as long as an &lt;strong&gt;en dash&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;mark&gt;One-year-old puppy&lt;/mark&gt;&lt;/li&gt;
&lt;li&gt;&lt;mark&gt;1997&amp;ndash;1999&lt;/mark&gt;&lt;/li&gt;
&lt;li&gt;&lt;mark&gt;but&amp;mdash;&lt;/mark&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Apostrophes should point downwards&lt;/p&gt;
&lt;p&gt;&lt;mark&gt;It&amp;rsquo;s me. In the &amp;rsquo;70s. Rock &amp;rsquo;n&amp;rsquo; Roll&lt;/mark&gt;&lt;/p&gt;
&lt;p&gt;Brackets&lt;/p&gt;
&lt;p&gt;&lt;mark&gt;(regular ones), [square ones], {curly ones}&lt;/mark&gt;&lt;/p&gt;
&lt;p&gt;Special characters&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Copyright: &lt;mark&gt;© 2022&lt;/mark&gt; (should appear in line with text)&lt;/li&gt;
&lt;li&gt;Trademark: &lt;mark&gt;Brand™, and Registered Tradmark®&lt;/mark&gt; (should appear as superscripts)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Slashes&lt;/p&gt;
&lt;p&gt;&lt;mark&gt;Slash/forward\backward&lt;/mark&gt;&lt;/p&gt;
&lt;p&gt;Foot and Inches: &lt;mark&gt;12&#39; 13&amp;quot;&lt;/mark&gt;&lt;/p&gt;
&lt;h2 id=&#34;ligatures&#34;&gt;
  Ligatures
  &lt;a href=&#34;#ligatures&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;There, figure, fft, ffi.&lt;/p&gt;
&lt;h2 id=&#34;block-quote&#34;&gt;
  Block quote
  &lt;a href=&#34;#block-quote&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Blockquote directly under a title&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Multiline blockquote
Without extra line in between&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A regular line.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Multiline blockquote&lt;/p&gt;
&lt;p&gt;With extra line in between&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A very long blockquote:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Their brother, indeed, was the only one of the party whom she could regard with any complacency. His anxiety for Jane was evident, and his attentions to herself most pleasing, and they prevented her feeling herself so much an intruder as she believed she was considered by the others. She had very little notice from any but him. Miss Bingley was engrossed by Mr. Darcy, her sister scarcely less so; and as for Mr. Hurst, by whom Elizabeth sat, he was an indolent man, who lived only to eat, drink, and play at cards, who when he found her prefer a plain dish to a ragout, had nothing to say to her.&lt;sup id=&#34;fnref1:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;images&#34;&gt;
  Images
  &lt;a href=&#34;#images&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Here is an inline image &lt;img
    src=&#34;https://powersnail.com/2022/test-md-page/snail-small.webp&#34; alt=&#34;test image&#34;srcset=&#34;https://powersnail.com/2022/test-md-page/snail-small.webp 128w&#34; width=&#34;128&#34;  height=&#34;128&#34; &gt;
. There isn&amp;rsquo;t really a good strategy to place an image that is taller than a line inside a sentence, in my opinion. It&amp;rsquo;s just a wacky form of content allowed by the HTML.&lt;/p&gt;
&lt;p&gt;Images put on their own line is better:&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2022/test-md-page/snail-small.webp&#34; alt=&#34;test image&#34;srcset=&#34;https://powersnail.com/2022/test-md-page/snail-small.webp 128w&#34; width=&#34;128&#34;  height=&#34;128&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;A bigger image:&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2022/test-md-page/snail-big.webp&#34; alt=&#34;test image&#34;srcset=&#34;https://powersnail.com/2022/test-md-page/snail-big.webp 400w&#34; width=&#34;400&#34;  height=&#34;400&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;A gigantic image:&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2022/test-md-page/snail-gigantic.webp&#34; alt=&#34;test image&#34;srcset=&#34;https://powersnail.com/2022/test-md-page/snail-gigantic-400w.webp 400w,/2022/test-md-page/snail-gigantic-600w.webp 600w,/2022/test-md-page/snail-gigantic-800w.webp 800w,/2022/test-md-page/snail-gigantic-1000w.webp 1000w,/2022/test-md-page/snail-gigantic-1200w.webp 1200w,/2022/test-md-page/snail-gigantic.webp 4000w&#34; width=&#34;4000&#34;  height=&#34;4000&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;A svg image:&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2022/test-md-page/snail.svg&#34; alt=&#34;svg image&#34; width=&#34;33.866666&#34;  height=&#34;33.866668&#34; style=&#34;max-width: 100%; height: auto&#34; width=&#34;33.866666&#34;  height=&#34;33.866668&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;A figure written in HTML:&lt;/p&gt;
&lt;figure&gt;
    &lt;img alt=&#34;Image inside a figure&#34; 
        src=&#34;./snail-big.webp&#34;&gt;
    &lt;figcaption&gt;
        Image inside a figure
    &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Some Markdown parser will always treat images as an inline element. There&amp;rsquo;s nothing an SSG or theme maker can do. So this &lt;code&gt;figure&lt;/code&gt; is written as raw HTML.&lt;/p&gt;
&lt;h2 id=&#34;lists&#34;&gt;
  Lists
  &lt;a href=&#34;#lists&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;A numbered list&lt;/li&gt;
&lt;li&gt;With many elements&lt;/li&gt;
&lt;li&gt;And a multi-
line item&lt;/li&gt;
&lt;li&gt;Then, some
&lt;ol&gt;
&lt;li&gt;sub&lt;/li&gt;
&lt;li&gt;items&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;An unnumbered list
&lt;ul&gt;
&lt;li&gt;sub list
&lt;ul&gt;
&lt;li&gt;sub sub list&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;A lot of levels
&lt;ul&gt;
&lt;li&gt;interlacing with
&lt;ul&gt;
&lt;li&gt;other
&lt;ul&gt;
&lt;li&gt;going deeper&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;shalower
&lt;ul&gt;
&lt;li&gt;deeper
&lt;ul&gt;
&lt;li&gt;and deeper&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Back out again&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;And see if the rendering is sensible&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;code-blocks&#34;&gt;
  Code blocks
  &lt;a href=&#34;#code-blocks&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Block with no language set.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;block_with_a_language&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;python&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;indent&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;multi&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;level&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;code&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;space&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;indent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;ord&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;space&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;ord&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;space&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Block with no language set that is super,  super,  super,  super,  super,  super,  super,  super,  super,  super,  super,  super,  super,  super,  super,  super,  super,  super,  super, long.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;A block with a super,  super,  super,  super,  super,  super,  super,  super,  super,  super,  super,  super,  super,  super,  super,  super,  super,  super,  super, long line&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;tables&#34;&gt;
  Tables
  &lt;a href=&#34;#tables&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;A simple table with very few columns and rows:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;simple&lt;/th&gt;
&lt;th&gt;table&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;item 1&lt;/td&gt;
&lt;td&gt;item 2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;A table with alignment parameters:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:left&#34;&gt;alignment&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;test&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;table&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;item 1&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;item 2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;item3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;item 1&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;item 2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;item3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;item 1&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;item 2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;item3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;item 1&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;item 2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;item3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;A table with many columns&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;table&lt;/th&gt;
&lt;th&gt;table&lt;/th&gt;
&lt;th&gt;table&lt;/th&gt;
&lt;th&gt;table&lt;/th&gt;
&lt;th&gt;table&lt;/th&gt;
&lt;th&gt;table&lt;/th&gt;
&lt;th&gt;table&lt;/th&gt;
&lt;th&gt;table&lt;/th&gt;
&lt;th&gt;table&lt;/th&gt;
&lt;th&gt;table&lt;/th&gt;
&lt;th&gt;table&lt;/th&gt;
&lt;th&gt;table&lt;/th&gt;
&lt;th&gt;table&lt;/th&gt;
&lt;th&gt;table&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;row 1&lt;/td&gt;
&lt;td&gt;row 1&lt;/td&gt;
&lt;td&gt;row 1&lt;/td&gt;
&lt;td&gt;row 1&lt;/td&gt;
&lt;td&gt;row 1&lt;/td&gt;
&lt;td&gt;row 1&lt;/td&gt;
&lt;td&gt;row 1&lt;/td&gt;
&lt;td&gt;row 1&lt;/td&gt;
&lt;td&gt;row 1&lt;/td&gt;
&lt;td&gt;row 1&lt;/td&gt;
&lt;td&gt;row 1&lt;/td&gt;
&lt;td&gt;row 1&lt;/td&gt;
&lt;td&gt;row 1&lt;/td&gt;
&lt;td&gt;row 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;row 2&lt;/td&gt;
&lt;td&gt;row 2&lt;/td&gt;
&lt;td&gt;row 2&lt;/td&gt;
&lt;td&gt;row 2&lt;/td&gt;
&lt;td&gt;row 2&lt;/td&gt;
&lt;td&gt;row 2&lt;/td&gt;
&lt;td&gt;row 2&lt;/td&gt;
&lt;td&gt;row 2&lt;/td&gt;
&lt;td&gt;row 2&lt;/td&gt;
&lt;td&gt;row 2&lt;/td&gt;
&lt;td&gt;row 2&lt;/td&gt;
&lt;td&gt;row 2&lt;/td&gt;
&lt;td&gt;row 2&lt;/td&gt;
&lt;td&gt;row 2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;A table with a very fat column:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;fat&lt;/th&gt;
&lt;th&gt;column&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;item 1&lt;/td&gt;
&lt;td&gt;item 2 is very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;some-random-tests&#34;&gt;
  Some random tests
  &lt;a href=&#34;#some-random-tests&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Language: 中文测试&lt;/li&gt;
&lt;li&gt;HTML embeded: &lt;br&gt;&lt;strong&gt;&lt;code&gt;&amp;lt;br&amp;gt;&amp;lt;strong&amp;gt;&lt;/code&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;References&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;Austen, Jane. &lt;em&gt;Pride and Prejudice&lt;/em&gt;. Standard Ebooks, 2014.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref1:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;Eliot, T. S. &lt;em&gt;Poetry&lt;/em&gt;. Standard Ebooks, 2017.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;Butterick, Matthew. &lt;em&gt;Practical Typography&lt;/em&gt;. &lt;a href=&#34;https://practicaltypography.com/line-length.html&#34;&gt;https://practicaltypography.com/line-length.html&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34;&gt;
&lt;p&gt;A test for reference&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">Chinese Caramel Color</title>
    <link rel="alternate">https://powersnail.com/2022/chinese-caramel-color/</link>
    <published>Wed, 02 Feb 2022 00:00:00 +0000</published>
    <updated>Wed, 02 Feb 2022 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2022/chinese-caramel-color/</id>
    <summary type="html">糖色: Chinese Caramel Color ## The iconic Chinese cuisine Red Braised Pork Belly has an appetizing, deep, brick-red</summary>
    <content type="html">&lt;h2 id=&#34;糖色-chinese-caramel-color&#34;&gt;
  糖色: Chinese Caramel Color
  &lt;a href=&#34;#%e7%b3%96%e8%89%b2-chinese-caramel-color&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The iconic Chinese cuisine Red Braised Pork Belly has an appetizing, deep, brick-red color. This comes from 糖色(tang se): caramel color. Sugar crystals are heated to a deep red color, and diluted with water. The result is a translucent shimmery red solution, more natural and appetizing than the pinkish red of 红曲粉 (red yeast rice powder), which is found on some Cantonese Char Siu.&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2022/chinese-caramel-color/red-braised-pork-belly.webp&#34; alt=&#34;Caramel color vs. red yeast rice powder&#34;srcset=&#34;https://powersnail.com/2022/chinese-caramel-color/red-braised-pork-belly-400w.webp 400w,/2022/chinese-caramel-color/red-braised-pork-belly.webp 512w&#34; width=&#34;512&#34;  height=&#34;256&#34; &gt;

    &lt;figcaption&gt;Compare the color of red braised pork belly vs. Char Siu&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;We can roughly break the process down to four stages: melting, bubbling, turning yellow, and turning red.&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2022/chinese-caramel-color/caramel-1.webp&#34; alt=&#34;Melting sugar&#34;srcset=&#34;https://powersnail.com/2022/chinese-caramel-color/caramel-1.webp 256w&#34; width=&#34;256&#34;  height=&#34;143&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;Melting sugar&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;To melt the sugar, turn on low heat and toss &lt;strong&gt;30 grams of sugar crystals&lt;/strong&gt; in the pot, with &lt;strong&gt;1 teaspoon of oil&lt;/strong&gt;, and &lt;strong&gt;30 grams of water&lt;/strong&gt;. Keep stirring, and knocking on the crystals with the back of your spoon (or spatula) to break them apart.&lt;/p&gt;
&lt;p&gt;You can use just the oil, or just the water, too; I find oil &amp;amp; water mixture to be easier to work with. Water makes it easier to melt the sugar in the initial stage, and oil helps to buffer the heat when the sugar starts caramelizing.&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2022/chinese-caramel-color/caramel-2.webp&#34; alt=&#34;Bubbling sugar&#34;srcset=&#34;https://powersnail.com/2022/chinese-caramel-color/caramel-2.webp 256w&#34; width=&#34;256&#34;  height=&#34;220&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;Bubbling&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;After the sugar melt, the syrup will start to bubble. Keep stirring.&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2022/chinese-caramel-color/caramel-3.webp&#34; alt=&#34;Syrup turning yellow&#34;srcset=&#34;https://powersnail.com/2022/chinese-caramel-color/caramel-3.webp 256w&#34; width=&#34;256&#34;  height=&#34;193&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;#97843A Light Yellow&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;When the syrup turns #97843A (light yellow), caramelization has begun. Continue to stir, and be extra careful now, because the syrup will change color very rapidly.&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2022/chinese-caramel-color/caramel-4.webp&#34; alt=&#34;Syrup&amp;amp;rsquo;s yellow color deepens&#34;srcset=&#34;https://powersnail.com/2022/chinese-caramel-color/caramel-4.webp 256w&#34; width=&#34;256&#34;  height=&#34;174&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;#996118 Deep Yellow&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;When the syrup turns #996118 (dark yellow), turn off the heat. The residual heat is enough to cook the caramel.&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2022/chinese-caramel-color/caramel-5.webp&#34; alt=&#34;Syrup turning red&#34;srcset=&#34;https://powersnail.com/2022/chinese-caramel-color/caramel-5.webp 256w&#34; width=&#34;256&#34;  height=&#34;172&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;&lt;h1 id=&#34;420c00-brick-red&#34;&gt;
  420C00 Brick Red
  &lt;a href=&#34;#420c00-brick-red&#34;&gt;&lt;small&gt;#&lt;/small&gt;&lt;/a&gt;
&lt;/h1&gt;
&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;When the syrup turns #420C00 (brick-red), pour 400 grams of boiling water into the pot to stop the cooking. Be careful: some violent splattering is to be expected. Give the solution a few more rounds of stirring to ensure that it is even.&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2022/chinese-caramel-color/caramel-6.webp&#34; alt=&#34;Syrup diluted with water&#34;srcset=&#34;https://powersnail.com/2022/chinese-caramel-color/caramel-6.webp 256w&#34; width=&#34;256&#34;  height=&#34;192&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;Pour water in to the pot&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h2 id=&#34;finalizing&#34;&gt;
  Finalizing
  &lt;a href=&#34;#finalizing&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2022/chinese-caramel-color/caramel-7.webp&#34; alt=&#34;Caramel color in a bowl&#34;srcset=&#34;https://powersnail.com/2022/chinese-caramel-color/caramel-7.webp 256w&#34; width=&#34;256&#34;  height=&#34;206&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;Final Product&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Here&amp;rsquo;s our finished Chinese caramel color in a bowl. To use it, scoop a generous amount into your braised dish at the beginning of cooking.&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2022/chinese-caramel-color/caramel-8.webp&#34; alt=&#34;Caramel color as compared with black tea&#34;srcset=&#34;https://powersnail.com/2022/chinese-caramel-color/caramel-8.webp 256w&#34; width=&#34;256&#34;  height=&#34;202&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;Caramel Color vs. Earl Grey&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;The caramel color should be roughly the same color as a cup of black tea. That&amp;rsquo;s Earl Grey in the metal spoon for your reference.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;
  Summary
  &lt;a href=&#34;#summary&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/2022/chinese-caramel-color/caramel-color.svg&#34; alt=&#34;Caramel Color Summary&#34;style=&#34;max-width: 100%; height: auto&#34;loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">A Warm-up for Chords: Bowing Planes Exercise</title>
    <link rel="alternate">https://powersnail.com/2022/bowing-planes-exercise/</link>
    <published>Mon, 31 Jan 2022 00:00:00 +0000</published>
    <updated>Mon, 31 Jan 2022 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2022/bowing-planes-exercise/</id>
    <summary type="html">Chord and Bowing Planes ## How do we roll a clean chord on the violin? Or, perhaps a better question: how do we consistently roll a clean chord?</summary>
    <content type="html">&lt;h2 id=&#34;chord-and-bowing-planes&#34;&gt;
  Chord and Bowing Planes
  &lt;a href=&#34;#chord-and-bowing-planes&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;How do we roll a clean chord on the violin? Or, perhaps a better question: how do we consistently roll a clean chord?&lt;/p&gt;
&lt;p&gt;In this short post, I&amp;rsquo;m going to focus on one element: bowing planes.&lt;/p&gt;
&lt;p&gt;There are roughly speaking 7 planes in violin bowing (if we disregard triple stops): G, GD, D, DA, A, AE, and E. When you play on a single note, there is a bit of wiggle room. When you play double-stops, the bow must stay at the plane steadily and accurately. A little deviation from the plane will cause the sound to suffer.&lt;/p&gt;
&lt;p&gt;For example, look at this &lt;a href=&#34;https://www.youtube.com/watch?v=G_CY6pesFhs&#34;&gt;video&lt;/a&gt; of Hilary Hahn playing Bach&amp;rsquo;s Sarabande in B Minor, especially starting at 0:45 where the camera shows the bow angle. Her movement is so precise. When she draws the bow, the bow stays in that plane without any deviation. And when she reaches for a different string, the bow snaps to a different plane, and then when it snaps back, it was exactly the same angle as before.&lt;/p&gt;
&lt;p&gt;Despite the &amp;ldquo;snap&amp;rdquo; being so swift, the music flows without any bump. This is because while her vertical movement is abrupt, the horizontal movement isn&amp;rsquo;t. When the elbow level changes, the forearm still draws the bow at a constant rate, so nothing sounds disrupted.&lt;/p&gt;
&lt;p&gt;It takes persistent practice to reach such a mastery command of the bow. But even if you&amp;rsquo;ve put in the time and effort, sometimes you can still get the feeling that your bow arm can&amp;rsquo;t find the planes. We naturally get rusty from time to time, and it shows when we play something chord heavy like Bach.&lt;/p&gt;
&lt;p&gt;Here is a little warm-up exercise that I use to prepare myself for chord-extensive pieces. It gives some anchors to where each plane is.&lt;/p&gt;
&lt;h2 id=&#34;exercise-one&#34;&gt;
  Exercise One
  &lt;a href=&#34;#exercise-one&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/images/bow-planes-exercise-legato.svg&#34; alt=&#34;Legato Exercise&#34; width=&#34;675&#34;  height=&#34;85.115&#34; style=&#34;max-width: 100%; height: auto&#34; width=&#34;675&#34;  height=&#34;85.115&#34; &gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;First, play a simple legato exercise, connecting each plane to the next. Since we are warming up the bow arm, keep your torso stationary. Change the plane with your elbow level only. The aim of this exercise is to find where the planes are, and get used to moving between them swiftly.&lt;/p&gt;
&lt;p&gt;When you cross from a single string to a double-stop, the double-stop must immediately ring. For instance, when crossing from G to GD, you must hear both G and D equally well. If D is airy, the elbow hasn&amp;rsquo;t dropped far enough. If G is airy, the elbow has overshot. The same principle applies for when crossing from GD to D. G must stop immediately.&lt;/p&gt;
&lt;p&gt;What you are looking for is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The bow speed remains steady throughout the whole exercise. No stopping. No speeding up.&lt;/li&gt;
&lt;li&gt;The bow angle is held steady in the plane when you play each note.&lt;/li&gt;
&lt;li&gt;The bow angle changes swiftly when you change the plane. No muddiness.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;exercise-two-dotted-rhythm&#34;&gt;
  Exercise Two: Dotted Rhythm
  &lt;a href=&#34;#exercise-two-dotted-rhythm&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;When breaking a chord, we must choose where and when to move from one plane to the next. An early break can make the chord sound more unified and with a stronger momentum. A late break put more emphasis on the first few notes, which is crucial for phrasing in some situations.&lt;/p&gt;
&lt;p&gt;Ideally, you should be able to break the chord anywhere on the bow. In his masterclass, soloist Kerson Leung instructed a student do a simple exercise for Bach: break the chord as early as you can; shorten the first double-stop as much as possible, while still make them ring. The aim, of course, is not to play every chord curtly, but to acquire the capability of breaking a chord at an arbitrary place without damaging the tone quality.&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/images/bow-planes-exercise-dotted-rhythm.svg&#34; alt=&#34;Dotted Rhythm Exercise&#34; width=&#34;675&#34;  height=&#34;201.57&#34; style=&#34;max-width: 100%; height: auto&#34; width=&#34;675&#34;  height=&#34;201.57&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;We can reify this exercise with dotted rhythm. Again, play with the same requirement as the first exercise: clean, immediate string crossing. Snap into the plane and draw the bow as steady as possible. Don&amp;rsquo;t fidget with the elbow level; if you didn&amp;rsquo;t arrive at the plane accurately, take a step back and redo the measure. Remember, the goal is to anchor your elbow.&lt;/p&gt;
&lt;p&gt;Increase the dotted ratio as needed.&lt;/p&gt;
&lt;h2 id=&#34;exercise-three-advanced-string-crossings&#34;&gt;
  Exercise Three: Advanced String Crossings
  &lt;a href=&#34;#exercise-three-advanced-string-crossings&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/images/bow-planes-exercise-string-crossings.svg&#34; alt=&#34;Advanced String Crossings&#34; width=&#34;675.78235&#34;  height=&#34;202.15199&#34; style=&#34;max-width: 100%; height: auto&#34; width=&#34;675.78235&#34;  height=&#34;202.15199&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;So far, we have limited ourselves in moving between neighboring planes. But chords can span up to seven planes, depending on the phrasing. Therefore, the third exercise is jumping from G-string to every other plane, and then jumping from E string backwards.&lt;/p&gt;
&lt;p&gt;To make a clean sound this time, we have one additional restraint. The passing planes in-between your targets must not make a sound. Your forearm still can&amp;rsquo;t stop, while your elbow level needs to jump through a bigger gap.&lt;/p&gt;
&lt;p&gt;From my experience, this is the part where you can &lt;em&gt;really&lt;/em&gt; drill in the anchor of each plane.&lt;/p&gt;
&lt;h2 id=&#34;applying-the-exercise&#34;&gt;
  Applying the Exercise
  &lt;a href=&#34;#applying-the-exercise&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Take a chord from your repertoire, and deconstruct the chord into separated planes.&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/images/deconstructing-a-chord.svg&#34; alt=&#34;Deconstruction of a Chord&#34; width=&#34;675&#34;  height=&#34;114.86&#34; style=&#34;max-width: 100%; height: auto&#34; width=&#34;675&#34;  height=&#34;114.86&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;For example, to deconstruct the first chord of Bach&amp;rsquo;s Sarabande of B Minor, we separate the chord into double-stops and single notes, according to what phrasing you&amp;rsquo;d like. Use dotted rhythm to experiment with different momentum and emphasis.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;
  Conclusion
  &lt;a href=&#34;#conclusion&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The goal of this little 3-minute exercise is to anchor your elbow, to etch into your muscle memory the location of each bowing plane. You want to hear steady tone, consistent angles, and swift string crossings.&lt;/p&gt;
&lt;p&gt;You can download the whole exercise &lt;a href=&#34;https://powersnail.com/files/Bowing_Planes_Exercise.pdf&#34;&gt;here&lt;/a&gt;. It is licensed under &lt;a href=&#34;http://creativecommons.org/licenses/by-sa/4.0/?ref=chooser-v1&#34;&gt;CC BY-SA 4.0&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Happy practice!&lt;/p&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">Theme-less Hugo, Almost Pure HTML, Styled with MVP CSS</title>
    <link rel="alternate">https://powersnail.com/2022/hugo-mvp-css/</link>
    <published>Wed, 12 Jan 2022 00:00:00 +0000</published>
    <updated>Wed, 12 Jan 2022 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2022/hugo-mvp-css/</id>
    <summary type="html">Theme-less Hugo ## As popular as theming is, I can&amp;rsquo;t help but feel unsatisfied by a plug-and-use theme made by someone else.</summary>
    <content type="html">&lt;h2 id=&#34;theme-less-hugo&#34;&gt;
  Theme-less Hugo
  &lt;a href=&#34;#theme-less-hugo&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;As popular as theming is, I can&amp;rsquo;t help but feel unsatisfied by a plug-and-use theme made by someone else. From WordPress to Jekyll to Hugo, no theme ever stopped me from tinkering with the underlying templates and CSS, during which, the theme inevitably becomes more coupled with my blog and content. This is because while the templates are usually generic enough for the body of blog articles, they are often quite specific on other elements: about, headers, footers, navigation bars, etc. And to customize those elements, I&amp;rsquo;m practically re-writing the website.&lt;/p&gt;
&lt;p&gt;When I started with Hugo, I chose the theme &lt;a href=&#34;https://github.com/mavidser/hugo-rocinante&#34;&gt;Rocinante&lt;/a&gt;, for its clean appearance, and partially for its name, which comes from one of my favorite novels of all time. I forked the theme, and kept maintaining two repositories: the blog itself, and the theme. As more modifications were made, the two codebases tangled with each other so deeply, that I often wonder where I should put a certain element.&lt;/p&gt;
&lt;p&gt;I decided to go theme-less, when the theme no longer bear any resemblance to the original Rocinante. There&amp;rsquo;s no point in maintaining two sets of code if they cannot be decoupled.&lt;/p&gt;
&lt;p&gt;Theme-less Hugo is easy: I just needed the templates, everything in the &lt;code&gt;layouts&lt;/code&gt; directory, to scaffold the site. So, I copied the skeleton code&amp;mdash;&lt;code&gt;layouts&lt;/code&gt;, and &lt;code&gt;assets&lt;/code&gt; for the styles&amp;mdash;into my blog, and removed the &lt;code&gt;themes&lt;/code&gt; directory.&lt;/p&gt;
&lt;p&gt;In fact, I think if one has finished theme-shopping, and would like to start making customizations, the first thing to do is to copy the theme into their main project, and delete &lt;code&gt;themes&lt;/code&gt;. It makes the website whole, the workflow more coherent, the workspace better organized, the commit history saner.&lt;/p&gt;
&lt;h2 id=&#34;semantic-html-and-mvpcss&#34;&gt;
  Semantic HTML and MVP.CSS
  &lt;a href=&#34;#semantic-html-and-mvpcss&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I have very little need for advanced topography or animations. My blog is just a bunch of static files hosted on GitHub Pages; nothing Fancy.&lt;/p&gt;
&lt;p&gt;This is, therefore, a very suitable use case for a classless CSS framework like &lt;a href=&#34;https://andybrewer.github.io/mvp/&#34;&gt;MVP.CSS&lt;/a&gt;. Overall, I think MVP does a fantastic job.&lt;/p&gt;
&lt;p&gt;A few things that I don&amp;rsquo;t like about it:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Block quotes. MVP centers and enlarges the text in block quote, as if I&amp;rsquo;m hanging an inspirational epigram on the wall, which doesn&amp;rsquo;t fit the semantic role of block quotes. It&amp;rsquo;s simply a quotation that occupies a paragraph; it&amp;rsquo;s part of my content, a link in the linear chain of words, not a flyout or illustration. MVP already has &lt;code&gt;&amp;lt;section&amp;gt;&amp;lt;aside&amp;gt;&lt;/code&gt; to deal with that.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Links without underlines. This makes the website less accessible to color-blind readers, or anyone who reads on a monochrome monitor.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Alternating table row colors. Not a fault of MVP. This is merely a pet peeve of mine.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;With regard to code blocks, Hugo defaults to rendering code highlighting with inline style of fixed colors, which is awkward when MVP can react to system-wise dark theme. So, I configured Hugo to output code blocks with CSS classes, and output two themes, &lt;code&gt;friendly&lt;/code&gt; and &lt;code&gt;dracula&lt;/code&gt;, for light and dark themes respectively.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# To generate the CSS files&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;hugo gen chromastyles --style&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;friendly &amp;gt; assets/css/_friendly.css
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;hugo gen chromastyles --style&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;dracula &amp;gt; assets/css/_dracula.css&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-scss&#34; data-lang=&#34;scss&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// style.scss
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// To include both themes
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;@import&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;friendly&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;@media&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;prefers-color-scheme&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;ni&#34;&gt;dark&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;@import&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;dracula&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;# config.toml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;markup&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;markup&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;highlight&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;noClasses&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I then colored the website with a dark banner image of Bach&amp;rsquo;s manuscript, and a color scheme generated from a picture of a violin. To ensure that the colors have enough contrast, I generated them with &lt;a href=&#34;https://bottosson.github.io/posts/oklab/&#34;&gt;Oklab&lt;/a&gt; color space, and it seems to be passing accessibility tests so far. It might be a total overkill though, since a few colors on the spectrum are used. But what is a personal project without a few overkills?&lt;/p&gt;
&lt;h2 id=&#34;mathjax-and-a-little-grievance-of-hugo&#34;&gt;
  MathJax, and a Little Grievance of Hugo
  &lt;a href=&#34;#mathjax-and-a-little-grievance-of-hugo&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The only JavaScript I use is &lt;a href=&#34;https://www.mathjax.org/&#34;&gt;MathJax&lt;/a&gt;. I&amp;rsquo;ve been considering to use its server-side rendering, but it seems that at the moment of writing this blog, Hugo does not support its use.&lt;/p&gt;
&lt;p&gt;In fact, Hugo does not support running its output HTML through an arbitrary command, and I think it&amp;rsquo;s a shame. There is a limit to what the &lt;code&gt;replace&lt;/code&gt; and &lt;code&gt;replaceRE&lt;/code&gt; could accomplish, which can be supplemented by custom filters written by other users.&lt;/p&gt;
&lt;p&gt;For instance, math equations can be easily rendered with LaTeX and converted to SVG. This will enable the embedding of arbitrary Tex elements, not just what MathJax supports, and at the same time, eliminates the need to bundle a JS library for client-side rendering.&lt;/p&gt;
&lt;p&gt;One thing that I can do is to add an extra step to &lt;code&gt;hugo build&lt;/code&gt;, and iterate through all the output HTML with whatever post-processing I want. But I do hope that this could be integrated into Hugo, so I don&amp;rsquo;t have to further butcher the GitHub Action file.&lt;/p&gt;
&lt;h2 id=&#34;final-thoughts&#34;&gt;
  Final Thoughts
  &lt;a href=&#34;#final-thoughts&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;You can find all the code to my blog &lt;a href=&#34;https://github.com/PowerSnail/PowerSnail.github.io&#34;&gt;here&lt;/a&gt;. My modifications to the theme, up to the point that I moved everything into the main repository, can be found &lt;a href=&#34;https://github.com/PowerSnail/hugo-rocinante&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">Tiramisu</title>
    <link rel="alternate">https://powersnail.com/2022/tiramisu/</link>
    <published>Sun, 09 Jan 2022 00:00:00 +0000</published>
    <updated>Sun, 09 Jan 2022 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2022/tiramisu/</id>
    <summary type="html">Inspirations ## My recipe is loosely adapted from this recipe, with sparks of inspiration collected from here and there.</summary>
    <content type="html">&lt;h2 id=&#34;inspirations&#34;&gt;
  Inspirations
  &lt;a href=&#34;#inspirations&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;My recipe is loosely adapted from &lt;a href=&#34;https://www.askchefdennis.com/the-best-tiramisu-you-will-ever-make&#34;&gt;this recipe&lt;/a&gt;, with sparks of inspiration collected from here and there.&lt;/p&gt;
&lt;h2 id=&#34;the-cream&#34;&gt;
  The Cream
  &lt;a href=&#34;#the-cream&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;To me, the essence of tiramisu is mascarpone. The creamy, milky fragrance, and the smooth texture are what make tiramisu so delicious and rich. Some recipes use additional heavy creams, but it&amp;rsquo;s unnecessary. Mascarpone is made from cream; all the flavors you like about cream are already inside mascarpone. Just buy enough mascarpone, and you have one less thing to whip.&lt;/p&gt;
&lt;p&gt;To make the creamy curd of tiramisu, first whip 4 egg yolks in a double boiler. Prepare a small pot with a bit of water, bring it up to a boil, and turn the heat down to a simmer. Place a bowl above the steam, and whisk the egg yolk for about 10 minutes, until it&amp;rsquo;s thick, viscous, and of a lighter color. Gradually add 60g of sugar during the process.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve found that adding all the sugar at once can make the whipping process very awkward, especially with non-fine sugar. The mixture becomes simultaneously sandy and liquidy, which not very easy to work with. So, I add sugar in 3 batches.&lt;/p&gt;
&lt;p&gt;While waiting for the yolks to cool down, whisk the mascarpone just a little, so it&amp;rsquo;s fluffier. It&amp;rsquo;s very easy to over-whisk mascarpone, so be careful. Fold in the yolks when they are cooled to room temperature.&lt;/p&gt;
&lt;p&gt;Optionally, drop a pinch of salt into the egg whites, whisk it to a stiff peak, and fold it into the cream as well. The whites have no flavor; all it does is to firm up the texture, and dilute the sweetness.&lt;/p&gt;
&lt;h2 id=&#34;coffee&#34;&gt;
  Coffee
  &lt;a href=&#34;#coffee&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Prepare 250g of coffee. Instant coffee works. As a coffee lover, this is not something that I thought I was ever going to say; but for tiramisu, it absolutely works. Double the powder to water ratio, so it&amp;rsquo;s strong enough. Or if you have an espresso machine, that&amp;rsquo;s even better.&lt;/p&gt;
&lt;p&gt;For extra fragrance, I steeped a bag of Earl Grey in the hot coffee for 2 minutes.&lt;/p&gt;
&lt;p&gt;Add a teaspoon of whatever liquor you like. Or if you are like me, who cannot drink actual alcohol, a few drops of rum extract works wonders.&lt;/p&gt;
&lt;h2 id=&#34;assembly&#34;&gt;
  Assembly
  &lt;a href=&#34;#assembly&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Roll the ladyfingers in the coffee, and place them nicely in a layer. They should be just wet enough, so that there&amp;rsquo;s enough liquid to work their way to the core over the next few hours, but not so much that the whole piece is dripping.&lt;/p&gt;
&lt;p&gt;On top them, spread a thick layer of cream. And layer the ladyfingers and creams until everything is used up.&lt;/p&gt;
&lt;h2 id=&#34;summary-card&#34;&gt;
  Summary Card
  &lt;a href=&#34;#summary-card&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Here is a printable summary card for the recipe:&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/images/tiramisu.svg&#34; alt=&#34;Summary Card&#34;style=&#34;max-width: 100%; height: auto&#34;&gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">A New Way of Presenting Recipes and Chicken Abodo</title>
    <link rel="alternate">https://powersnail.com/2022/a-new-way-of-presenting-recipes-and-chicken-abodo/</link>
    <published>Wed, 05 Jan 2022 00:00:00 +0000</published>
    <updated>Wed, 05 Jan 2022 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2022/a-new-way-of-presenting-recipes-and-chicken-abodo/</id>
    <summary type="html">Cooking for Engineers ## I bumped into a site called Cooking for Engineers today, and at the bottom of some recipes, they have this succinct table that summarizes the procedure in a refreshingly simple manner:</summary>
    <content type="html">&lt;h2 id=&#34;cooking-for-engineers&#34;&gt;
  Cooking for Engineers
  &lt;a href=&#34;#cooking-for-engineers&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I bumped into a site called &lt;a href=&#34;http://www.cookingforengineers.com/&#34;&gt;Cooking for Engineers&lt;/a&gt; today, and at the bottom of some recipes, they have this succinct table that summarizes the procedure in a refreshingly simple manner:&lt;/p&gt;


&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&#34;border: solid 1px&#34;&gt;&lt;span itemprop=&#34;ingredient&#34; itemscope=&#34;&#34; itemtype=&#34;http://data-vocabulary.org/RecipeIngredient&#34;&gt;&lt;span itemprop=&#34;amount&#34;&gt;3 chicken&lt;/span&gt; &lt;span itemprop=&#34;name&#34;&gt;breasts&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style=&#34;border: solid 1px&#34;&gt;brine&lt;/td&gt;&lt;td style=&#34;border: solid 1px&#34; rowspan=&#34;3&#34;&gt;season&lt;/td&gt;&lt;td style=&#34;border: solid 1px&#34; rowspan=&#34;3&#34; class=&#34;vertical&#34;&gt;cook medium-high&lt;/td&gt;&lt;td style=&#34;border: solid 1px&#34; rowspan=&#34;3&#34;&gt;remove&lt;/td&gt;&lt;td style=&#34;border: solid 1px&#34; colspan=&#34;3&#34; rowspan=&#34;3&#34; class=&#34;righthide&#34;&gt;&lt;/td&gt;&lt;td style=&#34;border: solid 1px&#34; rowspan=&#34;6&#34; class=&#34;vertical&#34;&gt;coat with sauce&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&#34;border: solid 1px&#34;&gt;&lt;span itemprop=&#34;ingredient&#34; itemscope=&#34;&#34; itemtype=&#34;http://data-vocabulary.org/RecipeIngredient&#34;&gt;&lt;span itemprop=&#34;name&#34;&gt;salt&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style=&#34;border: solid 1px&#34; rowspan=&#34;2&#34; class=&#34;righthide&#34;&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&#34;border: solid 1px&#34;&gt;&lt;span itemprop=&#34;ingredient&#34; itemscope=&#34;&#34; itemtype=&#34;http://data-vocabulary.org/RecipeIngredient&#34;&gt;&lt;span itemprop=&#34;name&#34;&gt;pepper&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&#34;border: solid 1px&#34;&gt;&lt;span itemprop=&#34;ingredient&#34; itemscope=&#34;&#34; itemtype=&#34;http://data-vocabulary.org/RecipeIngredient&#34;&gt;&lt;span itemprop=&#34;amount&#34;&gt;4 oz. (120 g)&lt;/span&gt; &lt;span itemprop=&#34;name&#34;&gt;button mushrooms&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style=&#34;border: solid 1px&#34;&gt;slice&lt;/td&gt;&lt;td style=&#34;border: solid 1px&#34; colspan=&#34;3&#34; class=&#34;righthide&#34;&gt;&lt;/td&gt;&lt;td style=&#34;border: solid 1px&#34;&gt;cook 1 min.&lt;/td&gt;&lt;td style=&#34;border: solid 1px&#34; rowspan=&#34;2&#34; class=&#34;vertical&#34;&gt;reduce&lt;/td&gt;&lt;td style=&#34;border: solid 1px&#34; rowspan=&#34;3&#34; class=&#34;vertical&#34;&gt;reduce&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&#34;border: solid 1px&#34;&gt;&lt;span itemprop=&#34;ingredient&#34; itemscope=&#34;&#34; itemtype=&#34;http://data-vocabulary.org/RecipeIngredient&#34;&gt;&lt;span itemprop=&#34;amount&#34;&gt;1 cup&lt;/span&gt; &lt;span itemprop=&#34;name&#34;&gt;sweet marsala wine&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style=&#34;border: solid 1px&#34; colspan=&#34;5&#34; class=&#34;righthide&#34;&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style=&#34;border: solid 1px&#34;&gt;&lt;span itemprop=&#34;ingredient&#34; itemscope=&#34;&#34; itemtype=&#34;http://data-vocabulary.org/RecipeIngredient&#34;&gt;&lt;span itemprop=&#34;amount&#34;&gt;4 Tbs.&lt;/span&gt; &lt;span itemprop=&#34;name&#34;&gt;heavy cream&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;td style=&#34;border: solid 1px&#34; colspan=&#34;6&#34; class=&#34;righthide&#34;&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;* Copied from &lt;a href=&#34;http://www.cookingforengineers.com/recipe/59/Chicken-Mushroom-Marsala&#34;&gt;this recipe&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The drawback of this method is that it&amp;rsquo;s not easily written in Markdown, which is sadly the backbone of Hugo. Markdown table is not as flexible as the HTML one, but the HTML one, with a lot of spans, is not readable inside a markdown file. Not to mention the fact that I probably have to further mess with the CSS to hide some cell walls.&lt;/p&gt;
&lt;h2 id=&#34;modernist-cuisine&#34;&gt;
  Modernist Cuisine
  &lt;a href=&#34;#modernist-cuisine&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I encountered another website Modernist Cuisine, which, too, offered their own summary card for each recipe. Instead of a hacky HTML table, they chose to upload an image of a better-formatted table, like the one on this &lt;a href=&#34;https://modernistcuisine.com/recipes/hanukkah-short-ribs/&#34;&gt;page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s not as succinct as the approach taken by Cooking for Engineers. The pro is that the procedure is listed in chronological order. The con is that it&amp;rsquo;s not immediately obvious what can be made in parallel.&lt;/p&gt;
&lt;p&gt;But, it&amp;rsquo;s actually more readable, and aesthetically more pleasing. In fact, the aesthetics of the table reminds me of LaTeX and the famous &lt;a href=&#34;https://ctan.org/pkg/booktabs&#34;&gt;booktabs&lt;/a&gt; package.&lt;/p&gt;
&lt;p&gt;So, I decided to go with the Modernist&amp;rsquo;s approach.&lt;/p&gt;
&lt;h2 id=&#34;chicken-abodo&#34;&gt;
  Chicken Abodo
  &lt;a href=&#34;#chicken-abodo&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Chicken Abodo is a famous dish from the Philippines, which I first saw on &lt;a href=&#34;http://www.kenjilopezalt.com/&#34;&gt;J. Kenji López-Alt&lt;/a&gt;&amp;rsquo;s YouTube channel. At the time I took some short notes on my phone:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-markdown&#34; data-lang=&#34;markdown&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; Sear the chicken, lightly salted
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; Prepare a bunch of garlic, bay leaves, sugar, black pepper
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; Add ground pepper and pepper corns
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; Add garlic, bay leaves, sugar, and sauce,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; Ratio by weight: 1 vinegar : 2/3 soy sauce : 2/3 sugar
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;- Simmer for 1 hour&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Since then, I&amp;rsquo;ve nailed down the quantities of the ingredients more precisely. To re-document this recipe, I wrote this Latex document:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-latex&#34; data-lang=&#34;latex&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;\documentclass&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;article&lt;span class=&#34;nb&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;\usepackage&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;[dvipsnames]&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;xcolor&lt;span class=&#34;nb&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;\usepackage&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;booktabs&lt;span class=&#34;nb&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;\usepackage&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;multirow&lt;span class=&#34;nb&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;\usepackage&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;palatino&lt;span class=&#34;nb&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;\thispagestyle&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;empty&lt;span class=&#34;nb&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;\setlength&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;\tabcolsep&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;}{&lt;/span&gt;16pt&lt;span class=&#34;nb&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;\newcommand&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;\tabletitle&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;}&lt;/span&gt;[1]&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;\midrule\multicolumn&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;3&lt;span class=&#34;nb&#34;&gt;}{&lt;/span&gt;l&lt;span class=&#34;nb&#34;&gt;}{&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;\textbf&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;\color&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;BrickRed&lt;span class=&#34;nb&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;\MakeUppercase&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;#1&lt;span class=&#34;nb&#34;&gt;}}}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;\begin&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;document&lt;span class=&#34;nb&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;\begin&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;tabular&lt;span class=&#34;nb&#34;&gt;}{&lt;/span&gt;lll&lt;span class=&#34;nb&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;\toprule&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;\textbf&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;Ingredients&lt;span class=&#34;nb&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;\textbf&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;Quantity&lt;span class=&#34;nb&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;\textbf&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;Instruction&lt;span class=&#34;nb&#34;&gt;}&lt;/span&gt;                   &lt;span class=&#34;k&#34;&gt;\\&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;\tabletitle&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;Chicken Preparation&lt;span class=&#34;nb&#34;&gt;}&lt;/span&gt;                                                  &lt;span class=&#34;k&#34;&gt;\\&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Chicken Drumstick    &lt;span class=&#34;nb&#34;&gt;&amp;amp;&lt;/span&gt; 6                 &lt;span class=&#34;nb&#34;&gt;&amp;amp;&lt;/span&gt; Salt and sear the chicken              &lt;span class=&#34;k&#34;&gt;\\&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Garlic               &lt;span class=&#34;nb&#34;&gt;&amp;amp;&lt;/span&gt; 10 cloves         &lt;span class=&#34;nb&#34;&gt;&amp;amp;&lt;/span&gt; Crush the garlic                       &lt;span class=&#34;k&#34;&gt;\\&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Black Pepper         &lt;span class=&#34;nb&#34;&gt;&amp;amp;&lt;/span&gt; A bunch           &lt;span class=&#34;nb&#34;&gt;&amp;amp;&lt;/span&gt; Grind half of the pepper corns         &lt;span class=&#34;k&#34;&gt;\\&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                       &lt;span class=&#34;nb&#34;&gt;&amp;amp;&lt;/span&gt;                   &lt;span class=&#34;nb&#34;&gt;&amp;amp;&lt;/span&gt; Put the garlic and pepper into the pan &lt;span class=&#34;k&#34;&gt;\\&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;\tabletitle&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;Sauce&lt;span class=&#34;nb&#34;&gt;}&lt;/span&gt;                                                                &lt;span class=&#34;k&#34;&gt;\\&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Vinegar              &lt;span class=&#34;nb&#34;&gt;&amp;amp;&lt;/span&gt; 48g               &lt;span class=&#34;nb&#34;&gt;&amp;amp;&lt;/span&gt; Pour in the sauce                      &lt;span class=&#34;k&#34;&gt;\\&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Soy Sauce            &lt;span class=&#34;nb&#34;&gt;&amp;amp;&lt;/span&gt; 32g               &lt;span class=&#34;nb&#34;&gt;&amp;amp;&lt;/span&gt;                                        &lt;span class=&#34;k&#34;&gt;\\&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Sugar                &lt;span class=&#34;nb&#34;&gt;&amp;amp;&lt;/span&gt; 32g               &lt;span class=&#34;nb&#34;&gt;&amp;amp;&lt;/span&gt;                                        &lt;span class=&#34;k&#34;&gt;\\&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;\tabletitle&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;Simmering&lt;span class=&#34;nb&#34;&gt;}&lt;/span&gt;                                                            &lt;span class=&#34;k&#34;&gt;\\&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                       &lt;span class=&#34;nb&#34;&gt;&amp;amp;&lt;/span&gt;                   &lt;span class=&#34;nb&#34;&gt;&amp;amp;&lt;/span&gt; Add water to cover 2/3 of the chicken  &lt;span class=&#34;k&#34;&gt;\\&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                       &lt;span class=&#34;nb&#34;&gt;&amp;amp;&lt;/span&gt;                   &lt;span class=&#34;nb&#34;&gt;&amp;amp;&lt;/span&gt; Bring to a boil; simmer for 1 hour     &lt;span class=&#34;k&#34;&gt;\\&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;\bottomrule&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;\end&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;tabular&lt;span class=&#34;nb&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;\end&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;{&lt;/span&gt;document&lt;span class=&#34;nb&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And to convert this into an image, which tightly bounds the table rather than being a full letter sized white page, I rendered the document into a &lt;code&gt;DVI&lt;/code&gt; file and converted it into &lt;code&gt;SVG&lt;/code&gt; with &lt;code&gt;dvisvgm&lt;/code&gt;. The tool automatically crops the image, so it doesn&amp;rsquo;t end being a full letter sized page.&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/images/chicken-abodo.svg&#34; alt=&#34;Recipe Summary for Chicken Abodo&#34;style=&#34;max-width: 100%; height: auto&#34;&gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;This is the final result of a printable, succinct, summary card for my chicken abodo recipe. After reading on the web (and fiddling with HTML and CSS) for so long, there&amp;rsquo;s something very satisfying about LaTeX. It just looks nice.&lt;/p&gt;
&lt;p&gt;I then wrote a &lt;a href=&#34;https://github.com/casey/just&#34;&gt;Justfile&lt;/a&gt; recipe to automate the process:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;latex-svg name:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    mkdir -p output
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    latex --output-directory=output/ --output-format=dvi static/latex/{{ name }}.tex
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    dvisvgm --stdout -O -n output/{{ name }}.dvi &amp;gt; static/images/{{ name }}.svg&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The option &lt;code&gt;-n&lt;/code&gt; causes the SVG to turn all the glyphs into paths. Using fonts causes the browser to substitute the fonts, which is desirable in some cases, but not in a LaTeX document where the placement of elements are fixed.&lt;/p&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">&amp;ldquo;And Then There Were None&amp;rdquo; Reading Notes</title>
    <link rel="alternate">https://powersnail.com/2021/and-then-there-were-none/</link>
    <published>Wed, 24 Feb 2021 00:00:00 +0000</published>
    <updated>Wed, 24 Feb 2021 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2021/and-then-there-were-none/</id>
    <summary type="html">Summary # The book was the execution of ten people, carried out on an isolated island. Ten people of very different backgrounds were invited, by various ruses, to come on to the island.</summary>
    <content type="html">&lt;h1 id=&#34;summary&#34;&gt;
  Summary
  &lt;a href=&#34;#summary&#34;&gt;&lt;small&gt;#&lt;/small&gt;&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;The book was the execution of ten people, carried out on an isolated island. Ten people of very different backgrounds were invited, by various ruses, to come on to the island. A recorded voice blared out accusations, that each of them had committed a murder and escaped the punishment of the law. One by one, they started dying, in the same manner as described by a nursery rhyme that was carved in their bedrooms. A rich young man died by poison. The maid died by sleeping pill overdose. No one else was on the island, so the murderer must be among themselves, but despite their effort at self-preservation, the killing continued. The general was killed by the sea. The butler was chopped by an axe. The old distinguished lady was again poisoned with cyanide, while a bumblebee was present, as a symbol for bee sting. They searched for poisons and weapons, but then, the Judge was shot when they rushed to help the young lady. The doctor ran out of the house and vanished at midnight. The ex-policeman was killed by a bear-shaped clock dropped from a window. The last two, Vera the young lady, and Lombard the shady hard man, found the corpse of the doctor floating in the sea. Now that there was no other option, Vera though Lombard was the murderer. She cheated him, stole his gun, and shot him dead. Then, as she came back to her room, she was so moved by the murder, the shooting, and the guilt, she committed suicide.&lt;/p&gt;
&lt;p&gt;The judge was the mastermind. His death was faked by the doctor, who was convinced that faking the death would help draw out the real murderer.&lt;/p&gt;
&lt;h1 id=&#34;head-hopping&#34;&gt;
  Head Hopping
  &lt;a href=&#34;#head-hopping&#34;&gt;&lt;small&gt;#&lt;/small&gt;&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;The book was written in 10 view points, and constantly hopping from one head to another.&lt;/p&gt;
&lt;p&gt;For instance,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;He had said it with acceptance—almost with welcome.&lt;/p&gt;
&lt;p&gt;But to Vera the words—the thought—brought rebellion.&lt;/p&gt;
&lt;p&gt;No, it should not be the end.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Despite the fact that we know the criminal is among them, and that we get to read their inner thoughts from time to time, there was still the mystery.&lt;/p&gt;
&lt;p&gt;The trick was that the Judge was positioned to be the authority in the very beginning, and the readers are already accustomed to his sharp judgment, when he remained composed and shrewd later. He was also very good at making deductions using only the evidence that had been presented to him, rather than leaking the fact that he knew everything all along. He misled the other nine people, in exactly the same way the author mystified the readers.&lt;/p&gt;
&lt;p&gt;The head hopping worked well in this book, as it shows the fear, the anxiety, the curiosity, that were presented in each mind. There were no lead detective to solve the crime; each of them were equally suspicious and suspected.&lt;/p&gt;
&lt;h1 id=&#34;annotations&#34;&gt;
  Annotations
  &lt;a href=&#34;#annotations&#34;&gt;&lt;small&gt;#&lt;/small&gt;&lt;/a&gt;
&lt;/h1&gt;
&lt;h2 id=&#34;chapter-one&#34;&gt;
  Chapter One
  &lt;a href=&#34;#chapter-one&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Page 3 Location 100&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Vera Claythorne, in a third-class carriage with five other travellers in it, leaned her head back and shut her eyes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Page 5 Location 128&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Philip Lombard, summing up the girl opposite in a mere flash of his quick moving eyes thought to himself:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Page 6 Location 155&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In a non-smoking carriage Miss Emily Brent sat very upright as was her custom. She was sixty-five and she did not approve of lounging. Her father, a Colonel of the old school, had been particular about deportment.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Page 8 Location 184&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;General Macarthur looked out of the carriage window. The train was just coming into Exeter, where he had to change. Damnable, these slow branch line trains! This place, Soldier Island, was really no distance at all as the crow flies.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Page 9 Location 198&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Dr. Armstrong was driving his Morris across Salisbury Plain. He was very tired … Success had its penalties.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Page 11 Location 221&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Tony Marston, roaring down into Mere, thought to himself: &amp;ldquo;The amount of cars crawling about the roads is frightful. Always something blocking your way. And they will drive in the middle of the road! Pretty hopeless driving in England, anyway…. Not like France where you really could let out….&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Page 12 Location 237&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Mr. Blore was in the slow train from Plymouth. There was only one other person in his carriage, an elderly seafaring gentleman with a bleary eye. At the present moment he had dropped off to sleep.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;chapter-two&#34;&gt;
  Chapter Two
  &lt;a href=&#34;#chapter-two&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Page 21 Location 378&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Down the steep track into the village a car was coming. A car so fantastically powerful, so superlatively beautiful that it had all the nature of an apparition. At the wheel sat a young man, his hair blown back by the wind. In the blaze of the evening light he looked, not a man, but a young God, a Hero God out of some Northern Saga. He touched the horn and a great roar of sound echoed from the rocks of the bay. It was a fantastic moment. In it, Anthony Marston seemed to be something more than mortal. Afterwards more than one of those present remembered that moment.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;chapter-four&#34;&gt;
  Chapter Four
  &lt;a href=&#34;#chapter-four&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Page 51 Location 842&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Whoever it was who enticed us here, that person knows or has taken the trouble to find out a good deal about us all.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;chapter-eight&#34;&gt;
  Chapter Eight
  &lt;a href=&#34;#chapter-eight&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Page 101 Location 1612&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;He cleared his throat and said in a would-be conversational tone: &amp;ldquo;Nice peaceful spot you&amp;rsquo;ve found for yourself, sir.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;chapter-nine&#34;&gt;
  Chapter Nine
  &lt;a href=&#34;#chapter-nine&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Page 130 Location 2076&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Blore said: &amp;ldquo;That&amp;rsquo;s what happened. Absolutely. And that lets out the judge, Mr. Lombard, myself and Miss Claythorne.&amp;rdquo; His voice was loud and jubilant. Mr. Justice Wargrave, bringing a cold eye to bear upon him, murmured: &amp;ldquo;Ah, but does it? We must take into account every possible eventuality.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;chapter-eleven&#34;&gt;
  Chapter Eleven
  &lt;a href=&#34;#chapter-eleven&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Page 149 Location 2358&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Philip Lombard had the habit of waking at daybreak. He did so on this particular morning. He raised himself on an elbow and listened. The wind had somewhat abated but was still blowing. He could hear no sound of rain….&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Page 150 Location 2381&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The little party moved through the house. Rogers&amp;rsquo; room, as Philip Lombard had already ascertained, was untenanted. The bed had been slept in, and his razor and sponge and soap were wet.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;chapter-sixteen&#34;&gt;
  Chapter Sixteen
  &lt;a href=&#34;#chapter-sixteen&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Page 216 Location 3420&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Aeons passed … worlds spun and whirled … Time was motionless … It stood still—it passed through a thousand ages…. No, it was only a minute or so … Two people were standing looking down on a dead man…. Slowly, very slowly, Vera Claythorne and Philip Lombard lifted their heads and looked into each other&amp;rsquo;s eyes….&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Page 217 Location 3440&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;He had said it with acceptance—almost with welcome.&lt;/p&gt;
&lt;p&gt;But to Vera the words—the thought—brought rebellion.&lt;/p&gt;
&lt;p&gt;No, it should not be the end.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Page 219 Location 3468&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;His quick brain was working. Which way—which method—talk her over—lull her into security or a swift dash—All his life Lombard had taken the risky way. He took it now. He spoke slowly, argumentatively: &amp;ldquo;Now look here, my dear girl, you just listen—&amp;rdquo; And then he sprang. Quick as a panther—as any other feline creature…. Automatically Vera pressed the trigger…. Lombard&amp;rsquo;s leaping body stayed poised in mid-spring then crashed heavily to the ground. Vera came warily forward, the revolver ready in her hand. But there was no need of caution. Philip Lombard was dead—shot through the heart….&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Christie, A. (2011). And Then There Were None.&lt;/p&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">南蛮鸡肉三明治 Chicken Sandwich with Nanban Sauce</title>
    <link rel="alternate">https://powersnail.com/2020/chicken-sandwitch-nanban-sauce/</link>
    <published>Fri, 21 Feb 2020 00:00:00 +0000</published>
    <updated>Fri, 21 Feb 2020 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2020/chicken-sandwitch-nanban-sauce/</id>
    <summary type="html">菜谱改编自 MASAの料理ABC1. 材料 /</summary>
    <content type="html">&lt;p&gt;菜谱改编自 &lt;em&gt;MASAの料理ABC&lt;/em&gt;&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2 id=&#34;材料--material&#34;&gt;
  材料 / Material
  &lt;a href=&#34;#%e6%9d%90%e6%96%99--material&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id=&#34;南蛮酱--nanban-sauce&#34;&gt;
  南蛮酱 / Nanban Sauce
  &lt;a href=&#34;#%e5%8d%97%e8%9b%ae%e9%85%b1--nanban-sauce&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;米淋, 一大勺 / Mirin, One table spoon&lt;/li&gt;
&lt;li&gt;酱油, 两大勺 / Soy Sauce, Two table spoon&lt;/li&gt;
&lt;li&gt;白醋, 两大勺 / White Vinegar, Two table spoon&lt;/li&gt;
&lt;li&gt;糖, 小半勺 / Sugar, Less than Half table spoon&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;煎鸡肉--pan-fried-chicken&#34;&gt;
  煎鸡肉 / Pan-fried Chicken
  &lt;a href=&#34;#%e7%85%8e%e9%b8%a1%e8%82%89--pan-fried-chicken&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;带皮去骨鸡腿肉 / Chicken Thigh, boneless, with skin&lt;/li&gt;
&lt;li&gt;盐 / Salt&lt;/li&gt;
&lt;li&gt;黑胡椒 / Black pepper&lt;/li&gt;
&lt;li&gt;淀粉或者面粉 / Starch or flour&lt;/li&gt;
&lt;li&gt;面包 / Bread&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;烹调--cooking&#34;&gt;
  烹调 / Cooking
  &lt;a href=&#34;#%e7%83%b9%e8%b0%83--cooking&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;鸡腿肉皮朝下，把厚的地方蝴蝶切，摊平&lt;/p&gt;
&lt;p&gt;Place the chicken thigh skin-side down; butterfly-cut to flatten the thigh.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;用刀尖浅戳鸡肉，断筋&lt;/p&gt;
&lt;p&gt;Poke the muscle with the tip of the knife lightly multiple times to cut connective tissues.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;均匀涂抹盐和胡椒，腌制 15 分钟，使鸡肉基本恢复成室温&lt;/p&gt;
&lt;p&gt;Evenly rub salt and pepper into the chicken thigh; rest for 15 minutes so the chicken gets to room temperature.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;热锅，少油，中大火，将鸡肉均匀沾粉，皮朝下放入锅中&lt;/p&gt;
&lt;p&gt;Hot pan, a little oil, medium-high heat. Cover the chicken with starch or flour. Into the pan skin-side down.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;煎至金黄，翻面&lt;/p&gt;
&lt;p&gt;Flip when the skin becomes golden.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;两面都金黄以后，加入酱汁，调成中火&lt;/p&gt;
&lt;p&gt;Add sauce when both sides are golden; turn heat to medium.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;拨动、翻面，让鸡肉吸收酱汁&lt;/p&gt;
&lt;p&gt;Move around and flip the chicken so it absorbs the sauce.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;关火，在锅中静置 5 分钟&lt;/p&gt;
&lt;p&gt;Turn off heat and rest for 5 minutes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;切两片面包，将多余的酱汁涂在内侧，夹好鸡肉&lt;/p&gt;
&lt;p&gt;Prepare two slices of bread, and spread extra sauce onto the slices. Place the chicken thigh between the slices.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;南蛮鸡肉三明治，完成！&lt;/p&gt;
&lt;p&gt;Chicken Sandwich with Nanban Sauce, Done!&lt;/p&gt;
&lt;h2 id=&#34;总结--summary&#34;&gt;
  总结 / Summary
  &lt;a href=&#34;#%e6%80%bb%e7%bb%93--summary&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;经过实验，沾粉的步骤只是为了吸收更多酱汁，淀粉和面粉区别不大。&lt;/p&gt;
&lt;p&gt;According to my experiments, it makes no difference using starch or flour, since the goal is to absorb more sauce.&lt;/p&gt;
&lt;p&gt;原版菜谱加了半勺糖，我减少了一点，更能突出酸味和鲜味。&lt;/p&gt;
&lt;p&gt;The original Nanban sauce recipe had half a table spoon of sugar. I used a little less than that to emphasize more on the acidity and umami.&lt;/p&gt;
&lt;h2 id=&#34;参考资料--references&#34;&gt;
  参考资料 / References
  &lt;a href=&#34;#%e5%8f%82%e8%80%83%e8%b5%84%e6%96%99--references&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;MASA. (2018, October 16). 宮崎風酸甜雞腿丼飯/Miyazaki Style Nanban Chicken Don |MASAの料理ABC - YouTube. &lt;a href=&#34;https://www.youtube.com/watch?v=p7BaHCJ6xiI&amp;amp;t=335s&#34;&gt;https://www.youtube.com/watch?v=p7BaHCJ6xiI&amp;amp;t=335s&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">&amp;ldquo;Pride and Prejudice&amp;rdquo; Reading Notes: Highlights and Annotations</title>
    <link rel="alternate">https://powersnail.com/2019/pride-and-prejudice-reading-notes/</link>
    <published>Tue, 17 Sep 2019 00:00:00 +0000</published>
    <updated>Tue, 17 Sep 2019 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2019/pride-and-prejudice-reading-notes/</id>
    <summary type="html">Summary of Pride and Prejudice ## A young intelligent woman, Elizabeth, had a tendency to judge people quickly. Based on impressions and gossips, she deemed Mr.</summary>
    <content type="html">&lt;h2 id=&#34;summary-of-_pride-and-prejudice_&#34;&gt;
  Summary of &lt;em&gt;Pride and Prejudice&lt;/em&gt;
  &lt;a href=&#34;#summary-of-_pride-and-prejudice_&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;A young intelligent woman, Elizabeth, had a tendency to judge people quickly. Based on impressions and gossips, she deemed Mr. Darcy proud, cruel, and exploiting his friend. When Mr. Darcy expressed his affection to her, Elizabeth bashed him with criticism and sarcasm. However, after meeting Mr. Darcy and his family on a trip, she realized that she had rushed her opinions. She was misled by Mr. Wickham, whom she had deemed to be trustworthy but was actually a long-time liar. When she found out that she had misjudged so many people along the way, she confessed to Mr. Darcy: both her apologies and her own affection towards him. In the end, Mr. Darcy still loved her, and they got married.&lt;/p&gt;
&lt;p&gt;The storytelling was magnificent and humorous. Not only did Elizabeth misjudged the characters of people, but also I - the reader - misjudged along with her. I also thought in the beginning that Mr. Darcy was obnoxious proud. It&amp;rsquo;s the way that author manipulated the narrative, showing only Elizabeth&amp;rsquo;s perspective, that achieved this effect. There were many intelligent conversations, yet the characters were distinct. Each smart people had their own way of showing their intelligence, some by infallible arguments, some by sarcasms and jokes.&lt;/p&gt;
&lt;h2 id=&#34;highlights-and-annotations&#34;&gt;
  Highlights and Annotations
  &lt;a href=&#34;#highlights-and-annotations&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;It is a truth universally acknowledged, that a single man in possession of a good fortune, must be in want of a wife.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The beginning sentence has a witty humor behind it, which set the tone of the whole book. The sort of sarcastic, smart, biting comments were often laid by the narrator, by Elizabeth, or by her father Mr. Bennet. In fact, Mr. Bennet in the most of the book was hardly a fatherly figure. His love and biases towards the daughters were apparent. However, when his least favorite daughter was potentially in danger, his worry and actions spoke for his actual feelings.&lt;/p&gt;
&lt;p&gt;Mr. Bennet had been an observer to the story for the majority of the book. He saw his own family and the world in a very picky lens; he did not participate in activities much; even when he did, he would take the chance to mock someone. The author might have projected herself onto this character, so she could point out ironies and mock the stupidity of people in a more engaging way.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Compliments always take you by surprise, and me never.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Elizabeth inherited Mr. Bennet&amp;rsquo;s humor, but added a self-mocking element to it. She often criticized herself and laughed about herself. She sometimes makes harsh judgments against herself, and sometimes makes fun of flaws in her own personality. Compared with Mr. Bennet&amp;rsquo;s stinging sarcasm, Elizabeth was humbler, yet prouder in herself at the same time.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Pride,&amp;rdquo; observed Mary, who piqued herself upon the solidity of her reflections,&amp;ldquo;is a very common failing, Vanity and pride are different things, though the words are often used synonymously. A person may be proud without being vain. Pride relates more to our opinion of ourselves, vanity to what we would have others think of us.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Mary is the other side of the author&amp;rsquo;s voice. In contrast to how mocking was expressed through Mr. Bennet&amp;rsquo;s mouth, the serious morals were delivered by Mary the nerd.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Undoubtedly,&amp;rdquo; replied Darcy, to whom this remark was chiefly addressed, &amp;ldquo;there is a meanness in all the arts which ladies sometimes condescend to employ for captivation. Whatever bears affinity to cunning is despicable.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Mr. Darcy was also smart and not stingy on his criticisms. But he did not use the deliberate sarcasm like Mr. Bennet. Mr. Darcy was too proud of himself to spend effort in crafting witty attacks just for the sake of mocking people. He was much more blunt in his criticism, while Mr. Bennet would go through winding roads that catch people by surprise. It was not in his character to deliberately hurt people, although at this point of the book, the real detailed Mr. Darcy had yet to be shown. His remarks were not lacking of intelligence, however. It originated from his clear mind, observant nature, and his pride to not losing an argument.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;…… Everything nourishes what is strong already. But if it be only a slight, thin sort of inclination, I am convinced that one good sonnet will starve it entirely away.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;(said by Mr. Darcy)&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Nothing is more deceitful,&amp;rdquo; said Darcy, &amp;ldquo;than the appearance of humility. It is often only carelessness of opinion, and sometimes an indirect boast.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot; Yes, vanity is a weakness indeed. But pride — where there is a real superiority of mind, pride will be always under good regulation.&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Mr. Darcy never hid his pride. He was so proud that even pride itself was to be proud of. The above quotes outlined that part of his character in clarity.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;An unhappy alternative is before you, Elizabeth. From this day you must be a stranger to one of your parents. Your mother will never see you again if you do not marry Mr. Collins, and I will never see you again if you do.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Almost anything could be seen as a joke to Mr. Bennet. He was like an old monk who had seen everything in the world, and therefore no longer find anything worthy of excitement (though he was quite disturbed later when Lydia was lost). Unlike a monk though, he loved to make fun of people.&lt;/p&gt;
&lt;h2 id=&#34;some-non-annotated-highlights&#34;&gt;
  Some Non-annotated Highlights
  &lt;a href=&#34;#some-non-annotated-highlights&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;There are few people whom I really love, and still fewer of whom I think well. The more I see of the world, the more am I dissatisfied with it; and every day confirms my belief of the inconsistency of all human characters, and of the little dependence that can be placed on the appearance of merit or sense.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;&amp;hellip;&amp;hellip; I have had the pleasure of your acquaintance long enough to know that you find great enjoyment in occasionally professing opinions which in fact are not your own.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;He spoke of apprehension and anxiety, but his countenance expressed real security.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Reflection must be reserved for solitary hours ; whenever she was alone, she gave way to it as the greatest relief ; and not a day went by without a solitary walk, in which she might indulge in all the delight of unpleasant recollections.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Mrs. Gardiner abused her stupidity.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;But he is a liberal master, I suppose, and that in the eye of a servant comprehends every virtue.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Assistance is impossible; condolence insufferable. Let them triumph over us at a distance, and be satisfied.&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;We all love to instruct, though we can teach only what is not worth knowing.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;I do not pretend to possess equal frankness with your ladyship. You may ask questions which I shall not choose to answer.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;bibliography&#34;&gt;
  Bibliography
  &lt;a href=&#34;#bibliography&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Austen, J. (2012). &lt;em&gt;Pride and Prejudice&lt;/em&gt;. Amazon Digital Services LLC.&lt;/p&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">Reading Notes on &amp;ldquo;The Adventure of Tom Sawyer&amp;rdquo;</title>
    <link rel="alternate">https://powersnail.com/2019/tom-sawyer-reading-notes/</link>
    <published>Sun, 23 Jun 2019 00:00:00 +0000</published>
    <updated>Sun, 23 Jun 2019 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2019/tom-sawyer-reading-notes/</id>
    <summary type="html">An Overall Review ## Tom Sawyer is a kid living in a small town, under the caring of his aunt.</summary>
    <content type="html">&lt;h2 id=&#34;an-overall-review&#34;&gt;
  An Overall Review
  &lt;a href=&#34;#an-overall-review&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Tom Sawyer is a kid living in a small town, under the caring of his aunt. He was a mischievous troublemaker both at school and at home. Wanting to be pirates, he and his friends ran off to an island and showed up later to their own funeral when the whole town thought they were dead.  They had their own superstitions, about life, death, and treasures. While pursuing their ceremony of burying a dead cat, they accidentally witnessed a murder and overheard the murderer&amp;rsquo;s plan of blaming it on to a drunk old man. Haunted since, Tom eventually grew the courage to testify against the murderer, who fled the court and disappeared. Later, he and Huck accidentally witness the murderer - now with a different appearance - talking about treasures, so they followed him. While all the thrills and fears happened, Tom managed to won back Becky&amp;rsquo;s heart at school when he took her punishment. The lovers ran off during an event and were lost in a cave, again seeing the murderer who was with his treasure. When Tom and Becky were back, the town sealed the cave, unknowing that the murderer was still in there, who died in hunger and despair. Tom and Huck dug up the treasures and became two rich children.&lt;/p&gt;
&lt;p&gt;The story of Tom Sawyer is alien to me. I have never experienced a similar childhood, as I was never the mischievous type and neither were my friends. Growing up without having a single fight or making a single prank to my teachers, the energetic trouble making couldn&amp;rsquo;t be farther from my own experiences. Being a Chinese living in an inland city, pirate life was alien even to my imagination. Tom was bold, while I was frankly quite timid.&lt;/p&gt;
&lt;p&gt;Yet the story moved me. In a way, I dreamed to do things similarly. My imagination had brought me to islands, mountains, oceans, etc. I wanted to become, though not a pirate, a swordsman of some sort, who travelled around the world. When I read the book, I saw children fulfilling absurd ideals. I saw teenagers frightened by their own imagination and overcame it. I saw while taking up responsibilities, Tom and his friends still fought back the grown-up world in their own way. In a nutshell, this is a story of victory of childhood.&lt;/p&gt;
&lt;p&gt;The book was a breeze to read. Mark Twain&amp;rsquo;s language was simple yet effective. By stitching together short actions, he showed scenes almost like a movie would. Especially for thrilling scenes - witnessing the murder for example, the short sentences followed one by one, creating the sensation of things happening in a very fast pace.&lt;/p&gt;
&lt;p&gt;There were no pretentious vocabularies (in fact he devoted a whole chapter criticizing the school event of writing pretentious words) or complex sentence structures. He chose the right verbs to succinctly describe people&amp;rsquo;s behavior; he sometimes threw witty insights of the characters&amp;rsquo; minds; he used plenty of conversations which served several purposes: describing the subject, reflecting the personality and mindset of the talker, and promoting the interaction between characters.&lt;/p&gt;
&lt;h2 id=&#34;quotes-i-liked&#34;&gt;
  Quotes I Liked
  &lt;a href=&#34;#quotes-i-liked&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id=&#34;chapter-1&#34;&gt;
  Chapter 1
  &lt;a href=&#34;#chapter-1&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;She seldom or never looked THROUGH them for so small a thing as a boy; they were her state pair, the pride of her heart, and were built for &amp;ldquo;style,&amp;rdquo; not service—she could have seen through a pair of stove-lids just as well.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This sentence is a good example of building up a lively, vivid image without using complicated structure or vocabularies.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;He had a citified air about him that ate into Tom&amp;rsquo;s vitals.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;ldquo;Ate into Tom&amp;rsquo;s vitals&amp;rdquo; Very vivid yet simple description of Tom&amp;rsquo;s discomfort meeting a new boy in town.&lt;/p&gt;
&lt;h3 id=&#34;chapter-2&#34;&gt;
  Chapter 2
  &lt;a href=&#34;#chapter-2&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Tom swept his brush daintily back and forth - stepped back to note the effect - added a touch here and there&amp;hellip;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The fluent language could just roll out of my tongue. &amp;ldquo;Swept&amp;rdquo; &amp;ldquo;stepped&amp;rdquo;, &amp;ldquo;back and forth&amp;rdquo; then &amp;ldquo;here and there&amp;rdquo;… The verbal structures gave the sentence a great eloquence.&lt;/p&gt;
&lt;p&gt;He described Tom&amp;rsquo;s movement in three semi-sentences, easily bringing to life the boy&amp;rsquo;s young energetic manner and the deliberate seriousness about this job.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;He had discovered a great law of human action, without knowing it - namely, that in order to make a man or a boy covet a thing, it is only necessary to make the thing difficult to attain. If he had been a great and wise philosopher, like the writer this book, he would now have comprehended that Work consists of whatever a body is OBLIGED to do, and that Play consists of whatever a body is not obliged to do.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;chapter-3&#34;&gt;
  Chapter 3
  &lt;a href=&#34;#chapter-3&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;This picture brought such an agony of pleasurable suffering that he worked it over and over again in his mind and set it up in new and varied lights, till he wore it threadbare.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;chapter-6&#34;&gt;
  Chapter 6
  &lt;a href=&#34;#chapter-6&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Tom was suffering in reality, now, so handsomely was his imagination working, and so his groans had gathered quite a genuine tone.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;chapter-8&#34;&gt;
  Chapter 8
  &lt;a href=&#34;#chapter-8&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;But the elastic heart of youth cannot be compressed into one constrained shape long at a time.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Tom flung off his jacket and trousers, turned a suspender into a belt, raked away some brush behind the rotten log, disclosing a rude bow and arrow, a lath sword and a tin trumpet, and in a moment had seized these things and bounded away, barelegged, with fluttering shirt.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Although the sentence is rather long, it is readable and easily comprehended. The author used a sequence of semi-sentences to describe consecutive actions, occasionally blending in a shift of camera to the effects of the actions. The shortness of each semi-sentence ensures that the cognitive burden is low; each action is directly following the previous one, so there is no need to keep track of the overall structure; the occasional clauses tightly relate to the preceding sentence, so they don&amp;rsquo;t interrupt the flow.&lt;/p&gt;
&lt;h3 id=&#34;chapter-9&#34;&gt;
  Chapter 9
  &lt;a href=&#34;#chapter-9&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;The hooting of a distant owl was all the sound that troubled the dead stillness. Tom&amp;rsquo;s reflections grew oppressive. He must force some talk.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;chapter-18&#34;&gt;
  Chapter 18
  &lt;a href=&#34;#chapter-18&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;That was Tom&amp;rsquo;s great secret - the scheme to return home with his brother pirates and attend their own funerals.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;chapter-21&#34;&gt;
  Chapter 21
  &lt;a href=&#34;#chapter-21&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;A prevalent feature in these compositions was a nursed and petted melancholy; another was a wasteful and opulent gush of &amp;ldquo;fine language&amp;rdquo;; another was a tendency to lug in by the ears particularly prized words and phrases until they were worn entirely out; and a peculiarity that conspicuously marked and marred them was the inveterate and intolerable sermon that wagged its crippled tail at the end of each and every one of them.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;chapter-26&#34;&gt;
  Chapter 26
  &lt;a href=&#34;#chapter-26&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;When they reached the haunted house there was something so weird and grisly about the dead silence that reigned there under the baking sun, and something so depressing about the loneliness and desolation of the place, that they were afraid, for a moment, to venture in.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;references&#34;&gt;
  References
  &lt;a href=&#34;#references&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Twain, M. (2014). &lt;em&gt;The Adventures of Tom Sawyer&lt;/em&gt;. CreateSpace Independent Publishing Platform.&lt;/p&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">A Constant Solution to Code-Fights Apple Boxes Problem</title>
    <link rel="alternate">https://powersnail.com/2017/apple-box/</link>
    <published>Fri, 06 Jan 2017 00:00:00 +0000</published>
    <updated>Fri, 06 Jan 2017 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2017/apple-box/</id>
    <summary type="html">An Apple box coding challenge</summary>
    <content type="html">&lt;h2 id=&#34;the-apple-boxes-problem&#34;&gt;
  The Apple Boxes Problem
  &lt;a href=&#34;#the-apple-boxes-problem&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The problem can be simply put:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Input: $k$&lt;/p&gt;
&lt;p&gt;Output: let $r$ be the sum of the square of each &lt;em&gt;even&lt;/em&gt; integer no larger than $k$, and $y$ be that of the &lt;em&gt;odd&lt;/em&gt;. Return $r - y$.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;the-naive-solution&#34;&gt;
  The Naive Solution
  &lt;a href=&#34;#the-naive-solution&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;We can loop through 1 to $k$, alternating between adding and subtracting.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;k&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;val&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;val&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There could be various optimizations, but nevertheless, the algorithm is linear with regard to $k$.&lt;/p&gt;
&lt;h2 id=&#34;constant-solution&#34;&gt;
  Constant Solution
  &lt;a href=&#34;#constant-solution&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;First, assume $k$ is even, so that we can perfectly pair up terms in $r$ and $y$. Observe that each pair is in the form of $x^2 - (x - 1)^2$. This can be transformed to $(x + x - 1)\cdot(x - x + 1) = (x - 1) + x$. When we add all pairs, it becomes a simple series: $1 + 2 + 3 + &amp;hellip; + k$. For example, for $k = 6$:&lt;/p&gt;
&lt;p&gt;$$
\begin{align*}
r &amp;amp;= 2^2 + 4^2 + 6^2 \\
y &amp;amp;= 1^2 + 3^2 + 5^2 \\
r - y &amp;amp;= (2^2 + 4^2 + 6^2) - (1^2 + 3^2 + 5^2) \\
&amp;amp;= (2^2 - 1^2) + (4^2 - 2^2) + (6^2 - 5^2) \\
&amp;amp;= 1 + 2 + 3 + 4 + 5 + 6 \\
&amp;amp;= \dfrac{6(1 + 6)}{2} \\
&amp;amp;= 21
\end{align*}
$$&lt;/p&gt;
&lt;p&gt;Thus, we can return $\dfrac{k(1 + k)}{2}$ for arbitrary &lt;em&gt;even&lt;/em&gt; $k$.&lt;/p&gt;
&lt;p&gt;What about &lt;em&gt;odd&lt;/em&gt; $k$? We can adjust the pairing a bit, and easily find that now we have $-\dfrac{k(1 + k)}{2}$.&lt;/p&gt;
&lt;h2 id=&#34;c-source-code&#34;&gt;
  C++ Source Code
  &lt;a href=&#34;#c-source-code&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;appleBoxes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;k&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sum&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;  &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;k&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;k&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;k&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;?&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nl&#34;&gt;sum&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">Count 1s in Range</title>
    <link rel="alternate">https://powersnail.com/2017/range-count-1/</link>
    <published>Fri, 06 Jan 2017 00:00:00 +0000</published>
    <updated>Fri, 06 Jan 2017 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2017/range-count-1/</id>
    <summary type="html">在 codefights 上做到了一个很有意思的题。给你 a, b 两</summary>
    <content type="html">&lt;p&gt;在 codefights 上做到了一个很有意思的题。给你 a, b 两个数，假设你构建了一个从 a 到 b 的 array，所有这些数的 binary representation 里面有多少个 1？&lt;/p&gt;
&lt;h1 id=&#34;naive-solution&#34;&gt;
  Naive Solution
  &lt;a href=&#34;#naive-solution&#34;&gt;&lt;small&gt;#&lt;/small&gt;&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;最简单的办法 (随手翻了两个别人的答案都是这个), 就是一个数一个数查有多少 1. 笨一点的手工查, 聪明一点的用 built-in function 查. 但是无论如何, 复杂度都是 O(b - a).&lt;/p&gt;
&lt;h1 id=&#34;logn-solution&#34;&gt;
  Log(n) Solution
  &lt;a href=&#34;#logn-solution&#34;&gt;&lt;small&gt;#&lt;/small&gt;&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;我们先思考一个简化版本的问题: 所有 &lt;code&gt;unsigned int (c++)&lt;/code&gt; 里面有多少 1? 答案是所有的 bit / 2, 因为当我们把所有数都写成 2 进制, 一半是 1, 一半是0.&lt;/p&gt;
&lt;p&gt;我们 generalize 一下: 对于任意的 $m$, 所有 $m$ 位的正整数里有 $(2^m * m) / 2$.&lt;/p&gt;
&lt;p&gt;当我们的上限不是&lt;em&gt;位数&lt;/em&gt;，而是一个数字 $b$, 我们可以把 $b$ 分成 3 各部分。假设 $b$ 不为 0, $b$ 的二进制形式应该是 $1xxxx$&amp;hellip; 假设 $b$ 有 $m + 1$ 位.&lt;/p&gt;
&lt;p&gt;现在以 $100&amp;hellip;0$ 为 &lt;code&gt;line&lt;/code&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;line&lt;/strong&gt; 一个 &amp;lsquo;1&amp;rsquo;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;below line&lt;/strong&gt;: 所有 $m$ 位数有$ (2^m * m) / 2$ 个 &amp;lsquo;1&amp;rsquo;. 这个数从前面的结论得来.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;above line&lt;/strong&gt;: 除去最左边的 $1$， 右边的部分又变成从 $0$ 开始查. 我们可以用一个简单地递归来解决这个部分。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;pseudo code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;allBits&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;sr&#34;&gt;//&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;不考虑负数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;sr&#34;&gt;//&lt;/span&gt; &lt;span class=&#34;ss&#34;&gt;basecase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;只有一位&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;m&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num_of_bits&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;m&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;onesBelowLine&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;m&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;line&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;onesAboveLine&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;allBits&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;onesBelowLine&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;onesAboveLine&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;下面回到原始问题，给定底线和上限，a, b， 我们可以简单地转换一下：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rangeBitCount&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;allBits&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;allBits&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;复杂度证明&#34;&gt;
  复杂度证明
  &lt;a href=&#34;#%e5%a4%8d%e6%9d%82%e5%ba%a6%e8%af%81%e6%98%8e&#34;&gt;&lt;small&gt;#&lt;/small&gt;&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;这个算法的复杂度很简单，因为这个 recursion 可以很容易的转换成 tail recursion，再变成复杂度相同的 iteration. 这个 iteration 每次去掉最高位的 1，因此最多有 $\log(b)$ 次循环；每次循环做了 constant 的基本算数，因此最后的复杂度应该是 $\log(b)$。&lt;/p&gt;
&lt;h1 id=&#34;c-source-code&#34;&gt;
  C++ Source Code
  &lt;a href=&#34;#c-source-code&#34;&gt;&lt;small&gt;#&lt;/small&gt;&lt;/a&gt;
&lt;/h1&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;allBits&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num_bit&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;31&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;__builtin_clz&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;unsigned&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num_bit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;count_below&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;num_bit&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;above&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;count_above&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;above&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;allBits&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;above&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;count_above&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;count_below&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;rangeBitCount&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;allBits&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;allBits&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">Valid Number - By DFA</title>
    <link rel="alternate">https://powersnail.com/2016/valid-number/</link>
    <published>Sun, 27 Nov 2016 00:00:00 +0000</published>
    <updated>Sun, 27 Nov 2016 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2016/valid-number/</id>
    <summary type="html">Introduction to the Problem ## The question asks the programmer to validate whether a string is a valid representation of a number.</summary>
    <content type="html">&lt;h2 id=&#34;introduction-to-the-problem&#34;&gt;
  Introduction to the Problem
  &lt;a href=&#34;#introduction-to-the-problem&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The question asks the programmer to validate whether a string is a valid representation of a number. After some trials, we find that the question accepts a few formats:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;pure integer&lt;/li&gt;
&lt;li&gt;real number (decimal representation), including omitted zero, for example &amp;ldquo;.5&amp;rdquo;, &amp;ldquo;12.&amp;rdquo;&lt;/li&gt;
&lt;li&gt;scientific number, that looks like &amp;ldquo;{Real Number}e{Integer}&amp;rdquo;&lt;/li&gt;
&lt;li&gt;integer and real number can be signed&lt;/li&gt;
&lt;li&gt;ignore any surrounding white spaces&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In order to solve the problem in linear time, most solutions set a few flags. This is simple, and quite efficient in both time and space. In fact, I don&amp;rsquo;t really consider this problem qualified for &lt;em&gt;hard&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Just to add some fun, this problem can be solved using a very textbook DFA. The code is elegant, less space efficient (but only for a constant amount) than the flag algorithm. In fact, the latter is just a compact, specialized DFA in essence. The trade-off is more variables and branching.&lt;/p&gt;
&lt;h2 id=&#34;the-algorithm&#34;&gt;
  The Algorithm
  &lt;a href=&#34;#the-algorithm&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The first step, we trim the string. There is probably not efficient in bringing white space processing into the DFA.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;inline&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;string&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;trim&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;string&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]),&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;// starting pointer
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;         &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;// ending pointer
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;&amp;#39;\0&amp;#39;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;isspace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;isspace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;--&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;&amp;#39;\0&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;dfa---states&#34;&gt;
  DFA - States
  &lt;a href=&#34;#dfa---states&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Any accepted string can be divided into a few parts:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;before decimal, the left part of a real number&lt;/li&gt;
&lt;li&gt;decimal&lt;/li&gt;
&lt;li&gt;after decimal, the right part of a real number&lt;/li&gt;
&lt;li&gt;e character&lt;/li&gt;
&lt;li&gt;the exponent, the right to &amp;rsquo;e&#39;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Any part could potentially empty. The (1) and (5) could potentially be preceded with a sign (&amp;rsquo;+&amp;rsquo; or &amp;lsquo;-&amp;rsquo;).&lt;/p&gt;
&lt;p&gt;Then, we can collect all states based on the grammar:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;state&lt;/th&gt;
&lt;th&gt;meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;START&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;starting state&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;REALLEFT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;before encountering any decimal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DOT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;encounter a regular decimal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;E&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;encounter an &amp;rsquo;e&amp;rsquo;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;REALRIGHT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;have encountered a decimal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DOT_E&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;have encountered a decimal whose left is omitted&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ERIGHT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;have encountered &amp;rsquo;e&amp;rsquo;, and is therefore part of the exponent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SIGN1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the sign on the left of the &amp;rsquo;e&#39;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SIGN2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the sign on the right of the &amp;rsquo;e&#39;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;FAULT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the faulty state&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The starting state is &lt;code&gt;START&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;FAULT&lt;/code&gt; is a special state, that the DFA will halt whenever it meets &lt;code&gt;FAULT&lt;/code&gt;, so that we do not have to process the rest of the string.&lt;/p&gt;
&lt;h3 id=&#34;dfa---transition&#34;&gt;
  DFA - Transition
  &lt;a href=&#34;#dfa---transition&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;The transition function is a matrix that maps (state, input char) to state.&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/images/valid-number-DFA.svg&#34; alt=&#34;DFA Transformation matrix&#34;style=&#34;max-width: 100%; height: auto&#34;&gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;em&gt;states&lt;/em&gt;&lt;/th&gt;
&lt;th&gt;DIGIT&lt;/th&gt;
&lt;th&gt;SIGN&lt;/th&gt;
&lt;th&gt;DOT&lt;/th&gt;
&lt;th&gt;E&lt;/th&gt;
&lt;th&gt;NDIGIT&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;START&lt;/td&gt;
&lt;td&gt;REALLEFT&lt;/td&gt;
&lt;td&gt;SIGN1&lt;/td&gt;
&lt;td&gt;DOT_E&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;REALLEFT&lt;/td&gt;
&lt;td&gt;REALLEFT&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;td&gt;DOT&lt;/td&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DOT&lt;/td&gt;
&lt;td&gt;REALRIGHT&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;td&gt;ERIGHT&lt;/td&gt;
&lt;td&gt;SIGN2&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;REALRIGHT&lt;/td&gt;
&lt;td&gt;REALRIGHT&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DOT_E&lt;/td&gt;
&lt;td&gt;REALRIGHT&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ERIGHT&lt;/td&gt;
&lt;td&gt;ERIGHT&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SIGN1&lt;/td&gt;
&lt;td&gt;REALLEFT&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;td&gt;DOT_E&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SIGN2&lt;/td&gt;
&lt;td&gt;ERIGHT&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;td&gt;FAULT&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/images/valid_number_dfa.svg&#34; alt=&#34;grammar&#34; width=&#34;473.47&#34;  height=&#34;503.12&#34; style=&#34;max-width: 100%; height: auto&#34; width=&#34;473.47&#34;  height=&#34;503.12&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&#34;dfa---termination&#34;&gt;
  DFA - Termination
  &lt;a href=&#34;#dfa---termination&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;The DFA will terminate when&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;input is depleted&lt;/li&gt;
&lt;li&gt;state is &lt;code&gt;FAULT&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The string will be accepted if the termination state is one of following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;REALLEFT&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;REALRIGHT&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ERIGHT&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DOT&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In all other cases, the format is somewhat faulty. For example, if the DFA ended at &lt;code&gt;E&lt;/code&gt;, then the string looks like &lt;code&gt;&amp;quot;{some number}e&amp;quot;&lt;/code&gt;, which is not acceptable.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;The running of the DFA is easy. Simply iterate over the input, and let the transition matrix do its magic.&lt;/p&gt;
&lt;h2 id=&#34;complete-code&#34;&gt;
  Complete Code:
  &lt;a href=&#34;#complete-code&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Solution&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;inline&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;string&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;trim&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;string&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;             &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;&amp;#39;\0&amp;#39;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;isspace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;isspace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;--&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;&amp;#39;\0&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;START&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;REALLEFT&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;DOT&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;E&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;REALRIGHT&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;DOT_E&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ERIGHT&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;6&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SIGN1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;7&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SIGN2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;DIGIT&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NDIGIT&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SIGN&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;G&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;45&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//  DIGIT       SIGN    DOT      E     NDIGIT
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;        &lt;span class=&#34;n&#34;&gt;REALLEFT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;   &lt;span class=&#34;n&#34;&gt;SIGN1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;DOT_E&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;REALLEFT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;   &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;DOT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;    &lt;span class=&#34;n&#34;&gt;E&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;      &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;REALRIGHT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;E&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;      &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;ERIGHT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;     &lt;span class=&#34;n&#34;&gt;SIGN2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;REALRIGHT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;E&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;      &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;REALRIGHT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;ERIGHT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;     &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;REALLEFT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;   &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;DOT_E&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;ERIGHT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;     &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;bool&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;isNumber&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;string&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;trim&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;prev&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;&amp;#39;\0&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;state&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;START&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;auto&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;state&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ch&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;isdigit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;?&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;DIGIT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;&amp;#39;.&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;?&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;DOT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;&amp;#39;e&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;?&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;E&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;&amp;#39;+&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;?&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;SIGN&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;&amp;#39;-&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;?&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;SIGN&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NDIGIT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;state&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;G&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;state&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;state&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;E&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;state&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;DOT_E&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;state&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SIGN1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;state&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SIGN2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;state&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;START&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;state&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FAULT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">Exceptional Control Flow</title>
    <link rel="alternate">https://powersnail.com/2016/control-flow-exception/</link>
    <published>Tue, 15 Nov 2016 00:00:00 +0000</published>
    <updated>Tue, 15 Nov 2016 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2016/control-flow-exception/</id>
    <summary type="html">Overview ## A processor accesses a sequence of instructions when it operates. The transition from one to the next, is called control transfer.</summary>
    <content type="html">&lt;h2 id=&#34;overview&#34;&gt;
  Overview
  &lt;a href=&#34;#overview&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;A processor accesses a sequence of instructions when it operates. The transition from one to the next, is called &lt;em&gt;control transfer&lt;/em&gt;. The sequence of transfers is called &lt;em&gt;control flow&lt;/em&gt;. The control flow is smooth when the transitions are always to the adjacent address. Operations such as &lt;code&gt;jump&lt;/code&gt;, &lt;code&gt;call&lt;/code&gt;, etc. will cause the control flow to be abrupt.&lt;/p&gt;
&lt;p&gt;There are other situations where the control flow is abruptly changed. For example, hardware timer, network packet arrival, etc. are events that have to be dealt with but not necessarily a part of the execution of the program. The system will likely deal with such situations with &lt;em&gt;exceptional control flow&lt;/em&gt; (ECF), a disruption to the control flow.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Application Level ECF: inter-process &lt;em&gt;signal&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;OS kernel Level ECF: context switches&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;exceptions&#34;&gt;
  Exceptions
  &lt;a href=&#34;#exceptions&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id=&#34;definition&#34;&gt;
  Definition
  &lt;a href=&#34;#definition&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;An &lt;em&gt;exception&lt;/em&gt; is an abrupt change in the control flow in response to some change in the processor&amp;rsquo;s state.&lt;/p&gt;
&lt;p&gt;An &lt;em&gt;event&lt;/em&gt; is a change in the processor&amp;rsquo;s state.&lt;/p&gt;
&lt;h3 id=&#34;exception-happening&#34;&gt;
  Exception Happening
  &lt;a href=&#34;#exception-happening&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;When the application is executing instruction $I_{curr}$, there is an event occurred.&lt;/p&gt;
&lt;p&gt;The event could be either caused by the instruction just occurred, or completely unrelated to the application. The processor will look up the &lt;em&gt;exception table&lt;/em&gt;, and make a procedure call to the &lt;em&gt;exception handler&lt;/em&gt;, which will process the particular kind of event. Then, depending on the event, three things can occur:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The handler returns, to $I_{curr}$&lt;/li&gt;
&lt;li&gt;The handler returns, to $I_{next}$&lt;/li&gt;
&lt;li&gt;The handler aborts the program&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;exception-handling&#34;&gt;
  Exception Handling
  &lt;a href=&#34;#exception-handling&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;The handling of exception involves both hardware and software.&lt;/p&gt;
&lt;p&gt;Each type of exception is assigned an integer &lt;em&gt;exception number&lt;/em&gt;, assigned by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The designer of the processor
&lt;ul&gt;
&lt;li&gt;divide by zero&lt;/li&gt;
&lt;li&gt;page faults&lt;/li&gt;
&lt;li&gt;memory access violations&lt;/li&gt;
&lt;li&gt;break-points&lt;/li&gt;
&lt;li&gt;arithmetic overflows&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;The OS kernel
&lt;ul&gt;
&lt;li&gt;system calls&lt;/li&gt;
&lt;li&gt;signals from external I/O devices&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At &lt;strong&gt;Boot time&lt;/strong&gt;, the OS creates the exception table, mapping each exception number to the address of the exception handler for the particular type of exception.&lt;/p&gt;
&lt;p&gt;The table&amp;rsquo;s base address is contained in a CPU register, &lt;em&gt;exception table base register&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;At &lt;strong&gt;Run time&lt;/strong&gt;, the processor detects the event, and determines the exception number $k$. Then it makes an indirect procedure call through the address in table[$k$].&lt;/p&gt;
&lt;p&gt;The procedure call is accompanied by a few operations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The processor pushes the address of $I_{curr}$ or $I_{next}$ on to the &lt;strong&gt;kernel stack&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;the control is transferred to the kernel, which means the exception handlers run in &lt;strong&gt;kernel mode&lt;/strong&gt;, that they have access to all system resources.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The return is a special operation &lt;code&gt;return from interrupt&lt;/code&gt;, which restores kernel mode to user mode.&lt;/p&gt;
&lt;h3 id=&#34;class-of-exceptions&#34;&gt;
  Class of Exceptions
  &lt;a href=&#34;#class-of-exceptions&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Class&lt;/th&gt;
&lt;th&gt;Cause&lt;/th&gt;
&lt;th&gt;Async/Sync&lt;/th&gt;
&lt;th&gt;Return behavior&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Interrupt&lt;/td&gt;
&lt;td&gt;Signal from I/O device&lt;/td&gt;
&lt;td&gt;Async&lt;/td&gt;
&lt;td&gt;Always returns to next instruction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trap&lt;/td&gt;
&lt;td&gt;Intentional exception&lt;/td&gt;
&lt;td&gt;Sync&lt;/td&gt;
&lt;td&gt;Always returns to next instruction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fault&lt;/td&gt;
&lt;td&gt;Potentially recoverable error&lt;/td&gt;
&lt;td&gt;Sync&lt;/td&gt;
&lt;td&gt;Might return to current instruction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Abort&lt;/td&gt;
&lt;td&gt;Nonrecoverable error&lt;/td&gt;
&lt;td&gt;Sync&lt;/td&gt;
&lt;td&gt;Never returns&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Table 1: Classes of Exceptions &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Async&lt;/em&gt;: means that the event (IO Interrupt) is not caused by execution of any instruction, but rather an asynchronous signal that an external IO device sends to the processor.&lt;/p&gt;
&lt;h4 id=&#34;interrupt-handling&#34;&gt;
  Interrupt Handling
  &lt;a href=&#34;#interrupt-handling&#34;&gt;&lt;small&gt;####&lt;/small&gt;&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;The handling of interrupt runs independent of the program. It is not caused by, has no impact on the current program. The processor notices the interrupt pin is set, and jumps to the interrupt handler. The handler will return to $I_{next}$, as though nothing has happened.&lt;/p&gt;
&lt;h4 id=&#34;traps-and-system-calls&#34;&gt;
  Traps and System Calls
  &lt;a href=&#34;#traps-and-system-calls&#34;&gt;&lt;small&gt;####&lt;/small&gt;&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;Traps are intentional exceptions, likely to help interface between user program and the kernel, which is a &lt;em&gt;system call&lt;/em&gt;. Trap handlers also return to $I_{next}$ like interrupt handlers.&lt;/p&gt;
&lt;p&gt;System Calls:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;read&lt;/code&gt;: file reading&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fork&lt;/code&gt;: create a new process&lt;/li&gt;
&lt;li&gt;&lt;code&gt;execve&lt;/code&gt;: loading a new program&lt;/li&gt;
&lt;li&gt;&lt;code&gt;exit&lt;/code&gt;: terminating the current process&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Remember that syscall runs in kernal mode and is thus different from normal procedure calls.&lt;/p&gt;
&lt;h4 id=&#34;faults&#34;&gt;
  Faults
  &lt;a href=&#34;#faults&#34;&gt;&lt;small&gt;####&lt;/small&gt;&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;Faults are error conditions that a handler might be able to correct. If the error is corrected, the handler will return to $I_{curr}$ (the faulting instruction), so it is re-executed. Otherwise, the handler will return to an abort routine to terminate the program&lt;/p&gt;
&lt;h4 id=&#34;aborts&#34;&gt;
  Aborts
  &lt;a href=&#34;#aborts&#34;&gt;&lt;small&gt;####&lt;/small&gt;&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;Aborts result from unrecoverable fatal errors, for example, DRAM bits corruption.&lt;/p&gt;
&lt;h3 id=&#34;example-exceptions-in-linuxx86-64-systems&#34;&gt;
  Example Exceptions in Linux/x86-64 Systems
  &lt;a href=&#34;#example-exceptions-in-linuxx86-64-systems&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Divide error&lt;/strong&gt;: divide by zero, usually ends up in &lt;code&gt;abort&lt;/code&gt;. (Floating exceptions)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;General protection fault&lt;/strong&gt;: usually because the program references an undefined area of virtual memory, or tries to write to read-only text segment. Usually ends up in &lt;code&gt;abort&lt;/code&gt;. (Segmentation Fault)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Page Fault&lt;/strong&gt;: Page of virtual memory is not resident in memory, needs to be retrieved from disk. The exception is &lt;code&gt;fault&lt;/code&gt;, and the handler will re-execute the faulting instruction after loading the page.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Machine check&lt;/strong&gt;: Fatal hardware error is detected during execution of the faulting instruction. It directly goes to &lt;code&gt;abort&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Syscalls:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Number&lt;/th&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;&lt;code&gt;read&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Read file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;code&gt;write&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;write file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;code&gt;open&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;open file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;code&gt;close&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;close file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;code&gt;stat&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Get info about file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mmap&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;map memory page to file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;&lt;code&gt;brk&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Reset the top the heap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;&lt;code&gt;dup2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;copy file descriptor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;33&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pause&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;suspend process until signal arrives&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;37&lt;/td&gt;
&lt;td&gt;&lt;code&gt;alarm&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;schedule delivery of alarm signal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;39&lt;/td&gt;
&lt;td&gt;&lt;code&gt;getpid&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;get process ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;57&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fork&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;create process&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;59&lt;/td&gt;
&lt;td&gt;&lt;code&gt;execve&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;execute a program&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;60&lt;/td&gt;
&lt;td&gt;&lt;code&gt;_exit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;terminate process&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;61&lt;/td&gt;
&lt;td&gt;&lt;code&gt;wait4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;wait for a process to terminate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;62&lt;/td&gt;
&lt;td&gt;&lt;code&gt;kill&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;send a signal to a process&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;c-and-syscalls&#34;&gt;
  C and Syscalls
  &lt;a href=&#34;#c-and-syscalls&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;C/C++ programs can call syscall directly. For example,&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;write&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;hello, world&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;13&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;_exit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In syscall, the syscall ID is passed in &lt;code&gt;%rax&lt;/code&gt;, and arguments are passed through &lt;code&gt;%rdi&lt;/code&gt;, &lt;code&gt;%rsi&lt;/code&gt;, &lt;code&gt;%rdi&lt;/code&gt;, &lt;code&gt;%r10&lt;/code&gt;, &lt;code&gt;%r8&lt;/code&gt;, &lt;code&gt;%r9&lt;/code&gt;, in order.&lt;/p&gt;
&lt;p&gt;Equivalent Assembly Program&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-nasm&#34; data-lang=&#34;nasm&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;.section&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;.data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nl&#34;&gt;string:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;.ascii&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;hello, world\n&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nl&#34;&gt;string_end:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;.equ&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;string_end&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;.section&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;.text&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;.global&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nl&#34;&gt;main:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;movq&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;           &lt;span class=&#34;err&#34;&gt;#&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;syscall&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;code&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;write&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;movq&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rdi&lt;/span&gt;           &lt;span class=&#34;err&#34;&gt;#&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;Arg1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;stdout&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;movq&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rsi&lt;/span&gt;      &lt;span class=&#34;err&#34;&gt;#&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;Arg2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;movq&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;         &lt;span class=&#34;err&#34;&gt;#&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;Arg3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;length&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;syscall&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;movq&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;60&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;          &lt;span class=&#34;err&#34;&gt;#&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;syscall&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;code&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;_exit&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;60&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;movq&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rdi&lt;/span&gt;           &lt;span class=&#34;err&#34;&gt;#&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;Arg1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;exist&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;syscall&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;processes&#34;&gt;
  Processes
  &lt;a href=&#34;#processes&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The concept of &lt;em&gt;process&lt;/em&gt; provides the illusion of&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;our program has exclusive use of CPU and memory&lt;/li&gt;
&lt;li&gt;the processor executes the instructions of our program without interruption&lt;/li&gt;
&lt;li&gt;the code and data of the program appear to be the only objects in memory&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A process is an instance of a program in execution. This means it includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the code in memory,&lt;/li&gt;
&lt;li&gt;the data in memory,&lt;/li&gt;
&lt;li&gt;the stack of the program&lt;/li&gt;
&lt;li&gt;the general-purpose registers&lt;/li&gt;
&lt;li&gt;the program counters&lt;/li&gt;
&lt;li&gt;environment variables&lt;/li&gt;
&lt;li&gt;the set of open file descriptors&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These states are the &lt;em&gt;context&lt;/em&gt; of the program.&lt;/p&gt;
&lt;h3 id=&#34;logical-control-flow&#34;&gt;
  Logical Control Flow
  &lt;a href=&#34;#logical-control-flow&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;We perceive the illusionary control flow, that registers, memory, etc. are changed step by step completely according to the instruction set of our program. This control flow is called &lt;strong&gt;Logical Control Flow&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;In reality, processes take turns to use the processor. Each process runs for a short period of time and is preempted (temporarily suspended), until the next turn.&lt;/p&gt;
&lt;p&gt;This short time period is called &lt;em&gt;time slice&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&#34;concurrent-flows&#34;&gt;
  Concurrent Flows
  &lt;a href=&#34;#concurrent-flows&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;A logical flow whose execution overlaps in time with another flow is called a concurrent flow. Two flows run &lt;em&gt;concurrently&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&#34;parallel-flows&#34;&gt;
  Parallel Flows
  &lt;a href=&#34;#parallel-flows&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;The concurrent flows that run on different processor cores or computers are called &lt;em&gt;parallel flows&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&#34;private-address-space&#34;&gt;
  Private Address Space
  &lt;a href=&#34;#private-address-space&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;The illusion that the program has exclusive use of address space is provided by &lt;em&gt;private address space&lt;/em&gt;. This &amp;ldquo;space&amp;rdquo; of addresses cannot be read/written by other programs, and therefore is exclusive to the program.&lt;/p&gt;
&lt;h3 id=&#34;user-mode-vs-kernel-mode&#34;&gt;
  User Mode vs Kernel Mode
  &lt;a href=&#34;#user-mode-vs-kernel-mode&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;The OS restricts each process what instructions can be executed and what memory space can be accessed. The processor provides the capability with a &lt;code&gt;mode bit&lt;/code&gt;.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;code&gt;mode bit&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;Mode&lt;/th&gt;
&lt;th&gt;Instruction&lt;/th&gt;
&lt;th&gt;Memory Space&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Kernel Mode&lt;/td&gt;
&lt;td&gt;Any Instruction&lt;/td&gt;
&lt;td&gt;Any Memory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;User Mode&lt;/td&gt;
&lt;td&gt;No Privileged Instruction&lt;/td&gt;
&lt;td&gt;No reference to code/data in kernel area&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Privileged Instruction: &lt;code&gt;syscall&lt;/code&gt; functions, including halt, change mode, I/O op, etc.&lt;/p&gt;
&lt;h4 id=&#34;proc&#34;&gt;
  /proc
  &lt;a href=&#34;#proc&#34;&gt;&lt;small&gt;####&lt;/small&gt;&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;/proc&lt;/code&gt; is a Linux file system mount of the kernal data structure. It allows the user to access general system attributes.&lt;/p&gt;
&lt;h3 id=&#34;context-switch&#34;&gt;
  Context Switch
  &lt;a href=&#34;#context-switch&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;The kernel maintains a context for each process. The context is the state that the kernel needs to restart a preempted process.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Values of general-purpose registers,&lt;/li&gt;
&lt;li&gt;floating-point registers&lt;/li&gt;
&lt;li&gt;program counter&lt;/li&gt;
&lt;li&gt;user&amp;rsquo;s stack&lt;/li&gt;
&lt;li&gt;status registers&lt;/li&gt;
&lt;li&gt;kernel&amp;rsquo;s stack&lt;/li&gt;
&lt;li&gt;various kernel data structure
&lt;ul&gt;
&lt;li&gt;page table&lt;/li&gt;
&lt;li&gt;process table&lt;/li&gt;
&lt;li&gt;file table&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Scheduling&lt;/strong&gt;, deciding to preempt a process and restart a preempted process. This is handled by &lt;strong&gt;scheduler&lt;/strong&gt;, a code in the kernel.&lt;/p&gt;
&lt;p&gt;The kernel can decide to switch when the process is waiting for a read. The IO device can take care of the work, so the kernel will switch to another process, until the IO device sends an interrupt signalling successful transfer of data into the memory.&lt;/p&gt;
&lt;h2 id=&#34;system-call-error-handling&#34;&gt;
  System Call Error Handling
  &lt;a href=&#34;#system-call-error-handling&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;When a system level function encounter an error, they return $-1$, and set the global integer variable &lt;code&gt;errno&lt;/code&gt; to indicate what went wrong.&lt;/p&gt;
&lt;p&gt;An error checking fork function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;unix_error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;msg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;fprintf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;%s: %s&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;msg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;strerror&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;errno&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;exit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;pid_t&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;Fork&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;pid_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;fork&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;// &amp;lt;- check for error return value
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;        &lt;span class=&#34;nf&#34;&gt;unix_error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Fork error&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;signals&#34;&gt;
  Signals
  &lt;a href=&#34;#signals&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;A signal is a small message that notifies a process that an event of some type has occurred in the system.&lt;/p&gt;
&lt;h3 id=&#34;sending-signal&#34;&gt;
  Sending Signal
  &lt;a href=&#34;#sending-signal&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;The kernel sends a signal because:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the kernel detects a system event&lt;/li&gt;
&lt;li&gt;a process invoked &lt;code&gt;kill&lt;/code&gt; function&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;process-group&#34;&gt;
  Process Group
  &lt;a href=&#34;#process-group&#34;&gt;&lt;small&gt;####&lt;/small&gt;&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;Each process belongs to exactly one process group. By default, a child process belongs to the same group as its parent.&lt;/p&gt;
&lt;p&gt;The Process Group ID can be read/write using &lt;code&gt;getpgrp&lt;/code&gt; and &lt;code&gt;setpgid&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id=&#34;binkill&#34;&gt;
  &lt;code&gt;/bin/kill&lt;/code&gt;
  &lt;a href=&#34;#binkill&#34;&gt;&lt;small&gt;####&lt;/small&gt;&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;/bin/kill -9 15213&lt;/code&gt; sends a signal 9 (SIGKILL) to process 15213.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/bin/kill -9 -15213&lt;/code&gt; sends a signal 9 to ever process in group 15213&lt;/p&gt;
&lt;h4 id=&#34;from-keyboard&#34;&gt;
  from Keyboard
  &lt;a href=&#34;#from-keyboard&#34;&gt;&lt;small&gt;####&lt;/small&gt;&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;A Unix shell has at most 1 foreground job and zero or more background jobs. Typing &lt;kbd&gt;ctrl&lt;/kbd&gt; + &lt;kbd&gt;c&lt;/kbd&gt; causes the kernel to send SIGINT to every process in the foreground process group. &lt;kbd&gt;ctrl&lt;/kbd&gt; + &lt;kbd&gt;z&lt;/kbd&gt; sends SIGTSTP signal to every process in the foreground process group, which pauses them.&lt;/p&gt;
&lt;h4 id=&#34;calling-kill-function&#34;&gt;
  Calling &lt;code&gt;kill&lt;/code&gt; function
  &lt;a href=&#34;#calling-kill-function&#34;&gt;&lt;small&gt;####&lt;/small&gt;&lt;/a&gt;
&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;sys/types.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;signal.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;kill&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;pid_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sig&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pid&lt;/code&gt; &amp;gt; 0, send &lt;code&gt;sig&lt;/code&gt; to process[&lt;code&gt;pid&lt;/code&gt;]&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pid&lt;/code&gt; = 0, send &lt;code&gt;sig&lt;/code&gt; to process group that current process belongs&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pid&lt;/code&gt; &amp;lt; 0, send &lt;code&gt;sig&lt;/code&gt; to process group [|&lt;code&gt;pid&lt;/code&gt;|]&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;calling-alarm-function&#34;&gt;
  Calling &lt;code&gt;alarm&lt;/code&gt; function
  &lt;a href=&#34;#calling-alarm-function&#34;&gt;&lt;small&gt;####&lt;/small&gt;&lt;/a&gt;
&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;unsigned&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;alarm&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;unsigned&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;secs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Arranges the kernel to send SIGALRM signal to the calling process in &lt;code&gt;secs&lt;/code&gt; seconds. If secs == 0, then no new alarm is scheduled.&lt;/p&gt;
&lt;p&gt;It returns the remaining seconds of previous alarm.&lt;/p&gt;
&lt;p&gt;A call of &lt;code&gt;alarm&lt;/code&gt; cancels all previous &lt;code&gt;alarm&lt;/code&gt;s.&lt;/p&gt;
&lt;h3 id=&#34;receiving-signal&#34;&gt;
  Receiving Signal
  &lt;a href=&#34;#receiving-signal&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;The kernel checks for any &lt;em&gt;pending and not blocked&lt;/em&gt; signals, when switching a process from kernel mode to user mode, i.e. from an Interrupt, syscall, or context switching.&lt;/p&gt;
&lt;p&gt;If there is no such signals, then it will proceed to $I_{next}$. Otherwise, the kernel will choose a signal and force the process to receive it. The receipt will trigger some action, and once the action is completed, the kernel proceeds to $I_{next}$.&lt;/p&gt;
&lt;p&gt;There is a default action associated with each signal; the user program can change it by using a &lt;code&gt;signal&lt;/code&gt; function&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;signal.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;typedef&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;sighandler_t&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;sighandler_t&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;signal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;signum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;sighandler_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;handler&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then &lt;code&gt;handler&lt;/code&gt; can be SIG_IGN (ignore), SIG_DFL (default), or the address of a user-defined function, a *signal handler.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;Figure 8.5, CSAPP&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">Code Optimizations</title>
    <link rel="alternate">https://powersnail.com/2016/optimization/</link>
    <published>Tue, 08 Nov 2016 00:00:00 +0000</published>
    <updated>Tue, 08 Nov 2016 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2016/optimization/</id>
    <summary type="html">An example: Transpose
for i in rows for j in cols b[i][j] = a[j][i]However, it might be the case that we do not know the size at compilation time, so we cannot statically declare this 2D array.</summary>
    <content type="html">&lt;p&gt;An example: &lt;strong&gt;Transpose&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rows&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;j&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cols&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, it might be the case that we do not know the size at &lt;em&gt;compilation time&lt;/em&gt;, so we cannot statically declare this 2D array. Therefore, for this to work, &lt;code&gt;b[i][j]&lt;/code&gt; needs to be a pointer to an array.&lt;/p&gt;
&lt;p&gt;To optimize, we use a 1-D array by flattening the table:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In order to make this statement more readable, we define a macro:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;# define RIDX(i, j, N) (i * N + j)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This macro will do a pure text replacement that replace all occurrence of &lt;code&gt;RIDX(i, j, N)&lt;/code&gt; by &lt;code&gt;(i * N + j)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For readability, let us assume that we can write &lt;code&gt;b[i, j]&lt;/code&gt; for this.&lt;/p&gt;
&lt;h3 id=&#34;which-one-is-better&#34;&gt;
  Which one is better?
  &lt;a href=&#34;#which-one-is-better&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;b[i, j] = a[j, i]&lt;/code&gt; vs. &lt;code&gt;b[j, i] = a[i, j]&lt;/code&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Temporal Locality&lt;/th&gt;
&lt;th&gt;Spacial Locality&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;b[i, j]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;a[j, i]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;b[j, i]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;a[i, j]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;So, either is bad.&lt;/p&gt;
&lt;p&gt;In order to optimize this function, we need to do something else.&lt;/p&gt;
&lt;p&gt;If we try to visualize the 2D array:&lt;/p&gt;
&lt;p&gt;For the cache lines, when we read &lt;code&gt;a[0, 0]&lt;/code&gt;, the next few numbers will be put into the same line. But when we read &lt;code&gt;b&lt;/code&gt;, we will be adding another cache line each time, as we jump across rows. If the array is big enough that we cannot put every row of &lt;code&gt;b&lt;/code&gt; into the cache lines. However, if the size is &lt;strong&gt;small&lt;/strong&gt; enough, we can start each cache lines aligned with each row, and therefore take advantage of spatial locality.&lt;/p&gt;
&lt;p&gt;We are going to use this to our advantage. We access each submatrix of the larger matrix, and transpose them one block a time. Because blocks are small, we enjoy the benefit of spatial locality if we pick the size smartly.&lt;/p&gt;
&lt;p&gt;After the block-wise transpose, each block is of the right order, and we enjoyed spatial locality.&lt;/p&gt;
&lt;p&gt;Note that for each block, the destination is still the desired position and therefore, when block-wise operation is done, the whole array is already transposed.&lt;/p&gt;
&lt;h3 id=&#34;right-size-of-block-size&#34;&gt;
  Right size of block size
  &lt;a href=&#34;#right-size-of-block-size&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;If &lt;code&gt;block.size&lt;/code&gt; is one (operation), this is meaningless
if &lt;code&gt;block.size&lt;/code&gt; is $N$, this is also meaningless.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Good!&lt;/strong&gt;: &lt;code&gt;block.size&lt;/code&gt; = $k \times ${cache line size}$&lt;/p&gt;
&lt;p&gt;&lt;em&gt;NOTE: although it is not possible to optimize the performance without benchmarking on the machine, we can generally optimize it based on some trials.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;implementation&#34;&gt;
  Implementation
  &lt;a href=&#34;#implementation&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;each&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;block&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;each&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cell&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;# do something&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In valid C language, this looks like&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;B_i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;B_i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;B_i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;B_j&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;B_j&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;B_j&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;B_i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;B_i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;B_size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;j&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;B_j&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;B_j&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;B_j&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;B_size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;c1&#34;&gt;// do something
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;            &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;how-is-this-better&#34;&gt;
  How is this better?
  &lt;a href=&#34;#how-is-this-better&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;If we only look at the inner loop, it still looks like we do not have spatial locality for at least one query. However, because of blocking, all information are in cache and locality does not matter anymore.&lt;/p&gt;
&lt;h3 id=&#34;loop-variables&#34;&gt;
  Loop variables
  &lt;a href=&#34;#loop-variables&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;B_j + B_size&lt;/code&gt; is run every time with the loop.
If we use a variable to store the value, the performance will increase.&lt;/p&gt;
&lt;h2 id=&#34;compiler-optimizations&#34;&gt;
  Compiler Optimizations
  &lt;a href=&#34;#compiler-optimizations&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id=&#34;disadvantage&#34;&gt;
  Disadvantage
  &lt;a href=&#34;#disadvantage&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Not changing semantics&lt;/li&gt;
&lt;li&gt;Limited Contact&lt;/li&gt;
&lt;li&gt;Conservative Heuristics
&lt;ul&gt;
&lt;li&gt;A *Guess Work**&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For example,&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will be optimized.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;float&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1e50&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1e50&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will not be optimized. Because this will actually result in &lt;code&gt;c = 0&lt;/code&gt; instead of &lt;code&gt;c = 1&lt;/code&gt; as in optimized code.&lt;/p&gt;
&lt;h2 id=&#34;loop-unrolling&#34;&gt;
  Loop Unrolling
  &lt;a href=&#34;#loop-unrolling&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nl&#34;&gt;Loop:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;cmp&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;%rdi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;%rax&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;jeg&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;End&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;addq&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;%rdi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;%rsi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;irmovq&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;$1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;%rcx&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;add&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;%rcx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;%rdi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;jmp&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;Loop&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nl&#34;&gt;End:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Only 2/5 of the operations are doing the actual work! The bookkeeping is taking a great portion of our time.&lt;/p&gt;
&lt;p&gt;The simple solution is to put more operations into the loop:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;N&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Caveat&lt;/strong&gt;: the unrolled loop operations might exceed &lt;code&gt;N&lt;/code&gt;, therefore we need to change the boundary: &lt;code&gt;for (int i = 0; i &amp;lt; N - 2; )&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If &lt;code&gt;N&lt;/code&gt; is big, this should not hurt the performance overall. The advantage of unrolling loops will be more important.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Unrolling Too Much&lt;/strong&gt;: instruction cache miss (But this is unlikely, as it would take quite a number of unrolling to do that)&lt;/p&gt;
&lt;h2 id=&#34;function-inlining&#34;&gt;
  Function Inlining
  &lt;a href=&#34;#function-inlining&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Difficulty 1: Moving arguments into the right place.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Caller/Callee Convention&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;%rax&lt;/code&gt; is a caller saved register. Before calling the subroutine, the caller need to push &lt;code&gt;%rax&lt;/code&gt; onto the stack, and pop it afterwards. So that the callee can change &lt;code&gt;%rax&lt;/code&gt; as he wants.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;These are tedious work to store register values. In order to avoid this, we inline functions.&lt;/p&gt;
&lt;p&gt;For example,&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;strlen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &lt;span class=&#34;c1&#34;&gt;// doing something
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;strlen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We place the content of &lt;code&gt;strlen&lt;/code&gt; before x, saving the return value as a variable and replace the call with the variable.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// doing something
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ans&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;retVal&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;// instead of return
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ans&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">Fractals</title>
    <link rel="alternate">https://powersnail.com/2016/fractals/</link>
    <published>Tue, 08 Nov 2016 00:00:00 +0000</published>
    <updated>Tue, 08 Nov 2016 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2016/fractals/</id>
    <summary type="html">Fractal # naming: fractional dimension
Definition: ## self-similar $$\to$ when zoomed in, look the same
Types: ## Exactly self-similar Statistically self-similar Exactly Self-similar ## If zoomed in, there is no way to tell that we have zoomed in.</summary>
    <content type="html">&lt;h1 id=&#34;fractal&#34;&gt;
  Fractal
  &lt;a href=&#34;#fractal&#34;&gt;&lt;small&gt;#&lt;/small&gt;&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;naming: fractional dimension&lt;/p&gt;
&lt;h2 id=&#34;definition&#34;&gt;
  Definition:
  &lt;a href=&#34;#definition&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;self-similar $$\to$ when zoomed in, look the same&lt;/p&gt;
&lt;h2 id=&#34;types&#34;&gt;
  Types:
  &lt;a href=&#34;#types&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Exactly self-similar&lt;/li&gt;
&lt;li&gt;Statistically self-similar&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;exactly-self-similar&#34;&gt;
  Exactly Self-similar
  &lt;a href=&#34;#exactly-self-similar&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;If zoomed in, there is no way to tell that we have zoomed in.&lt;/p&gt;
&lt;h3 id=&#34;sierpinski-carpet&#34;&gt;
  Sierpinski Carpet
  &lt;a href=&#34;#sierpinski-carpet&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/images/Sierpinski_carpet.jpg&#34; alt=&#34;Sierpinski Carpet&#34;srcset=&#34;https://powersnail.com/images/Sierpinski_carpet-400w.jpg 400w,/images/Sierpinski_carpet.jpg 600w&#34; width=&#34;600&#34;  height=&#34;600&#34; &gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;ul&gt;
&lt;li&gt;A square divided into 9 squares&lt;/li&gt;
&lt;li&gt;The center square is empty&lt;/li&gt;
&lt;li&gt;Each other square is divided again&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;koch-snowflake&#34;&gt;
  Koch Snowflake
  &lt;a href=&#34;#koch-snowflake&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/images/2000px-Koch_Snowflake_7th_iteration.svg.png&#34; alt=&#34;Koch Snowflake&#34;srcset=&#34;https://powersnail.com/images/2000px-Koch_Snowflake_7th_iteration.svg-400w.png 400w,/images/2000px-Koch_Snowflake_7th_iteration.svg-600w.png 600w,/images/2000px-Koch_Snowflake_7th_iteration.svg-800w.png 800w,/images/2000px-Koch_Snowflake_7th_iteration.svg-1000w.png 1000w,/images/2000px-Koch_Snowflake_7th_iteration.svg-1200w.png 1200w,/images/2000px-Koch_Snowflake_7th_iteration.svg.png 2000w&#34; width=&#34;2000&#34;  height=&#34;2000&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;ul&gt;
&lt;li&gt;Chop the lines into 3 Segments&lt;/li&gt;
&lt;li&gt;replace the middle one with equal lateral triangle&lt;/li&gt;
&lt;li&gt;Chop and replace each segment&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The important property is that when we zoom in on an edge, it is arbitrarily &amp;ldquo;bumpy&amp;rdquo; - non-smooth. This is similar to things like shorelines. There is a self-similarity in natural shorelines.&lt;/p&gt;
&lt;p&gt;However, shorelines are not as bumpy as Koch Snowflakes. They are smoother. Hence, we need a concept to describe the bumpiness.&lt;/p&gt;
&lt;h3 id=&#34;length-of-koch-snowflake&#34;&gt;
  Length of Koch Snowflake
  &lt;a href=&#34;#length-of-koch-snowflake&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Each Step increases the length to $$\dfrac{4}{3} \times$ original. Hence, Koch Snowflake is infinitely long.&lt;/p&gt;
&lt;p&gt;$$l_k = \dfrac{4}{3} l_{k-1}$&lt;/p&gt;
&lt;p&gt;Question: How quickly does Koch Snowflake&amp;rsquo;s length converge to infinity?&lt;/p&gt;
&lt;h3 id=&#34;measuring-length-of-fractal-line&#34;&gt;
  Measuring Length of Fractal Line
  &lt;a href=&#34;#measuring-length-of-fractal-line&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Different measuring scales lead to different length.&lt;/p&gt;
&lt;p&gt;From the starting point, jump a fixed distance, $$d_u$, and measure how many $d_u$ are there in the line.&lt;/p&gt;
&lt;p&gt;Each different $$d_u$ results in a unique length, and as $d_u$ approaches 0, the length measured approaches $\infty$&lt;/p&gt;
&lt;p&gt;The scale is related to length and this function describes the bumpiness of a fractal line. This is called &lt;strong&gt;Fractal Dimension&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Higher&lt;/em&gt; Fractal Dimension means more &lt;em&gt;bumpiness&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Lower&lt;/em&gt; Fractal Dimension means less &lt;em&gt;bumpiness&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;shorelinemountain-topology&#34;&gt;
  Shoreline/Mountain Topology
  &lt;a href=&#34;#shorelinemountain-topology&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Use fractal dimension to model a bumpy line, and computationally derive the line, rather than describing more details.&lt;/p&gt;
&lt;h2 id=&#34;statistically-self-similar&#34;&gt;
  Statistically Self-similar
  &lt;a href=&#34;#statistically-self-similar&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Recursive Tree: &lt;strong&gt;Tree&lt;/strong&gt; := Stick + &lt;strong&gt;Tree&lt;/strong&gt; + &lt;strong&gt;Tree&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Moreover, we need to take care of the angles, length and returning position.&lt;/p&gt;
&lt;p&gt;It becomes:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;- Stick
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;- Turn
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;- Tree  -&amp;gt; this will expand to the same routine
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;- Turn
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;- Tree  -&amp;gt; this will expand to the same routine
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;- Turn
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;- Backwards&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;l-system&#34;&gt;
  L-System
  &lt;a href=&#34;#l-system&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;The above process can be described by CFG:&lt;/p&gt;
&lt;p&gt;$$T:S\leftarrow T \rightarrow \rightarrow T \leftarrow \overline{S}$&lt;/p&gt;
&lt;p&gt;This use of CFG is called L-System.&lt;/p&gt;
&lt;h3 id=&#34;improvement-to-l-system-tree&#34;&gt;
  Improvement to L-System Tree
  &lt;a href=&#34;#improvement-to-l-system-tree&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Randomness : This introduces &lt;strong&gt;Statistically similar&lt;/strong&gt; fractal image.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The sub-parts are statistically similar to the original image, but not exactly the same.&lt;/p&gt;
&lt;p&gt;To create a nice tree, it is important to examine each tree. There is a &lt;strong&gt;grammar&lt;/strong&gt; to each type of tree, describing its patterns.&lt;/p&gt;
&lt;p&gt;However, sadly trees don&amp;rsquo;t grow by the fractal model.&lt;/p&gt;
&lt;h2 id=&#34;incorporating-randomness-into-fractals&#34;&gt;
  Incorporating Randomness Into Fractals
  &lt;a href=&#34;#incorporating-randomness-into-fractals&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Example Algorithm (&lt;em&gt;Subdivide and Offset&lt;/em&gt;)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;repeat
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    foreach segment
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        offset midpoint for random distance
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        hence create two segments&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;deeper repetition: bumpier&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;More sophisticated examples:&lt;/p&gt;
&lt;h3 id=&#34;height-map&#34;&gt;
  Height Map
  &lt;a href=&#34;#height-map&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;A raster vector of height&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Can represent any terrain with no overlapping height (not bumpy topology, water, etc.)&lt;/li&gt;
&lt;li&gt;Cannot represent extremely rocky terrain&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Diamond Square&lt;/strong&gt;&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/images/2998px-Diamond_Square.svg.png&#34; alt=&#34;Level 0&#34;srcset=&#34;https://powersnail.com/images/2998px-Diamond_Square.svg-400w.png 400w,/images/2998px-Diamond_Square.svg-600w.png 600w,/images/2998px-Diamond_Square.svg-800w.png 800w,/images/2998px-Diamond_Square.svg-1000w.png 1000w,/images/2998px-Diamond_Square.svg-1200w.png 1200w,/images/2998px-Diamond_Square.svg.png 2998w&#34; width=&#34;2998&#34;  height=&#34;640&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;ul&gt;
&lt;li&gt;Level 0: Four corners set to $$h = 0$&lt;/li&gt;
&lt;li&gt;Level 1: Mid-point $$m_1$ set to $h_1 += random$&lt;/li&gt;
&lt;li&gt;Level 2: Point on Edges aligned with $$m_1$, offset randomly&lt;/li&gt;
&lt;li&gt;Level 3: Mid-point of each sub-square, offset randomly&lt;/li&gt;
&lt;li&gt;&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The result could look something like:&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/images/Plasmafractal.gif&#34; alt=&#34;Diamond Square&#34;srcset=&#34;https://powersnail.com/images/Plasmafractal.gif 300w&#34; width=&#34;300&#34;  height=&#34;225&#34; loading=&#34;lazy&#34;&gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;The problem is the grid pattern is visible. There are &amp;lsquo;+&amp;rsquo; in the graph, so rotating the graph will be noticed (not entirely natural)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Use&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Applications&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;NOT good for terrain. Natural terrain has very few local minima. The minima will drain, and become global minima. This is not reflected by diamond square subdivision.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Clouds. Clouds density is similar to the patterns generated from diamond square subdivision.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Dirt. This could create &amp;ldquo;dirty&amp;rdquo; texture to human-created objects.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;perlin-fractal&#34;&gt;
  Perlin Fractal
  &lt;a href=&#34;#perlin-fractal&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;A perlin fractal is created by taking in a height map, downsize it, and fill itself with the small height map.&lt;/p&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">Binary Search Tree implemented by C++</title>
    <link rel="alternate">https://powersnail.com/2016/binary-search-tree/</link>
    <published>Sat, 27 Feb 2016 00:00:00 +0000</published>
    <updated>Sat, 27 Feb 2016 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2016/binary-search-tree/</id>
    <summary type="html">This is a simple implementation of binary search tree implemented by C++.</summary>
    <content type="html">&lt;p&gt;This is a simple implementation of binary search tree implemented by C++. Here are the methods of my BST:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Node&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;Node&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;left&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;right&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;parent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;BST&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;private&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;Node&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;BST&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;Node&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;root&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// Traversals
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;inorder&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;inorderRec&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Node&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;inorderIter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;preOrder&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;preOrderRec&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Node&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;postOrder&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;postOrderRec&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Node&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// Search Operations
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;n&#34;&gt;Node&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;find&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;Node&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;minimum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Node&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;Node&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;maximum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Node&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;Node&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;successor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Node&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;Node&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;predecessor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Node&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// Element Operation
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;insert&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;insert&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Node&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;remove&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;remove&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Node&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;transplant&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Node&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Node&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;bool&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;empty&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I will talk about some of the implementations. The complete source file can be found in my &lt;a href=&#34;https://github.com/PowerSnail/Algorithms-Practices&#34;&gt;algorithm repository&lt;/a&gt;. If you found any problem with the implementation, or anything that is worth adding to this, please leave a comment under this article or open an issue in the algorithm repository. This BST does not insert repeated element.&lt;/p&gt;
&lt;h2 id=&#34;basic-idea&#34;&gt;
  Basic Idea
  &lt;a href=&#34;#basic-idea&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Binary Search Tree is a basic data structure in computer science. It stores data, in my case some integers, into a tree-like structure.&lt;/p&gt;
&lt;p&gt;In a tree, there are nodes, which are the storage a piece of data and also connection to other nodes. A node can connect to its parent and its children. In other trees, there could be unlimited children, but for our case, a binary tree could have at most two children. Naturally, let&amp;rsquo;s call them left and right child respectively.&lt;/p&gt;
&lt;figure&gt;
    &lt;img
    src=&#34;https://powersnail.com/images/binarysearchtree.jpg&#34; alt=&#34;Binary Search Tree&#34;srcset=&#34;https://powersnail.com/images/binarysearchtree-400w.jpg 400w,/images/binarysearchtree-600w.jpg 600w,/images/binarysearchtree-800w.jpg 800w,/images/binarysearchtree-1000w.jpg 1000w,/images/binarysearchtree-1200w.jpg 1200w,/images/binarysearchtree.jpg 2445w&#34; width=&#34;2445&#34;  height=&#34;2308&#34; &gt;

    &lt;figcaption&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;The top node is called root, and the nodes that do not have a child are called leaves. There is a &lt;code&gt;nil&lt;/code&gt; sentinel node, which is not in the data structure but a &lt;a href=&#34;#sentinelNode&#34;&gt;useful element&lt;/a&gt; in our program.&lt;/p&gt;
&lt;h2 id=&#34;traversals&#34;&gt;
  Traversals
  &lt;a href=&#34;#traversals&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The recursive in-order traversal is easy to implement:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;BST&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;inorderRec&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Node&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;node&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;inorderRec&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;node&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;left&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;cout&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;node&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;key&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;inorderRec&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;node&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;right&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The iterative algorithm is slightly more complex. It involves two pointers, marking the current and previous position of our traversal. Although this is not recursive, we could still think of it using an inductive reasoning. We first set the initial states to root and nil (who is the parent of root):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;auto&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;root&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;auto&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;prev&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For an arbitrary iteration, there are three possibilities:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;prev&lt;/code&gt; is the parent of &lt;code&gt;x&lt;/code&gt;. It means we have been going downwards in the tree, and both left branch and right branch of &lt;code&gt;x&lt;/code&gt; has not yet been explored; then as in-order traversal requires, we go left from here.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prev&lt;/code&gt; is the left child of &lt;code&gt;x&lt;/code&gt;. This means we have just come back from the left branch, implying that the left is already printed. Now we have to print &lt;code&gt;x&lt;/code&gt; itself and going to the right.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prev&lt;/code&gt; is the right child of &lt;code&gt;x&lt;/code&gt;. This means we have printed everything in the subtree rooted at &lt;code&gt;x&lt;/code&gt;, and should now go up.&lt;/li&gt;
&lt;/ol&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;code&gt;prev&lt;/code&gt; pointing at&lt;/th&gt;
&lt;th&gt;printed subtree&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-&amp;gt; parent&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-&amp;gt; left&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;rooted at &lt;code&gt;left&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-&amp;gt; right&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;rooted at &lt;code&gt;x&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The trick here is to 1) progress the printing and 2) ensure that at the end of each iteration, the &lt;em&gt;invariant&lt;/em&gt; is preserved, i.e. the situation falls into one of the situations.&lt;/p&gt;
&lt;h4 id=&#34;prev-pointing-at-parent&#34;&gt;
  &lt;code&gt;prev&lt;/code&gt; Pointing at Parent
  &lt;a href=&#34;#prev-pointing-at-parent&#34;&gt;&lt;small&gt;####&lt;/small&gt;&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;Nothing has been printed, so we go to left directly;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;prev&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;left&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We need to consider the case where &lt;code&gt;left&lt;/code&gt; is nil, but this is easy because we can just throw &lt;code&gt;prev&lt;/code&gt; to left. This works because if we examine the &lt;em&gt;loop invariant&lt;/em&gt;, now the tree complies with the second situation.&lt;/p&gt;
&lt;h4 id=&#34;prev-pointing-at-left&#34;&gt;
  &lt;code&gt;prev&lt;/code&gt; Pointing at left
  &lt;a href=&#34;#prev-pointing-at-left&#34;&gt;&lt;small&gt;####&lt;/small&gt;&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;Left tree is already printed (we consider &lt;code&gt;nil&lt;/code&gt; as printed), so we try to go right. Don&amp;rsquo;t forget to first print out &lt;code&gt;x&lt;/code&gt; before entering right.&lt;/p&gt;
&lt;p&gt;There is a slight complication if &lt;code&gt;x&lt;/code&gt; is a leaf, as both children are &lt;code&gt;nil&lt;/code&gt;. We would not be able to know whether we have come back from left or right! The traversal will circle around at &lt;code&gt;x&lt;/code&gt; forever.&lt;/p&gt;
&lt;p&gt;&lt;img
    src=&#34;https://powersnail.com/images/fromlefttoright.jpg&#34; alt=&#34;From Left to Right&#34;srcset=&#34;https://powersnail.com/images/fromlefttoright-400w.jpg 400w,/images/fromlefttoright-600w.jpg 600w,/images/fromlefttoright-800w.jpg 800w,/images/fromlefttoright-1000w.jpg 1000w,/images/fromlefttoright-1200w.jpg 1200w,/images/fromlefttoright.jpg 2441w&#34; width=&#34;2441&#34;  height=&#34;2067&#34; loading=&#34;lazy&#34;&gt;
{:width=&amp;ldquo;36px&amp;rdquo;}.&lt;/p&gt;
&lt;p&gt;The solution is that we never come from right at a leaf node. When we reach a leaf node from its left, we directly move upwards.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;cout&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;key&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;right&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;// right branch is nil
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;n&#34;&gt;prev&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;prev&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;right&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;prev-pointing-at-right&#34;&gt;
  &lt;code&gt;prev&lt;/code&gt; Pointing at Right
  &lt;a href=&#34;#prev-pointing-at-right&#34;&gt;&lt;small&gt;####&lt;/small&gt;&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;We know &lt;code&gt;x&lt;/code&gt; subtree is all printed, so all we need to do is to move &lt;code&gt;x&lt;/code&gt; upwards.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;prev&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;insertion&#34;&gt;
  Insertion
  &lt;a href=&#34;#insertion&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Insertion always occur at leaf in a BST. Generally, we need to 1) find a proper leaf as the parent of our new node and 2) insert it into the proper child of the leaf.&lt;/p&gt;
&lt;h2 id=&#34;a-idsentinelnodea-sentinel-node&#34;&gt;
  &lt;a id=&#34;sentinelNode&#34;&gt;&lt;/a&gt; Sentinel Node
  &lt;a href=&#34;#a-idsentinelnodea-sentinel-node&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;How is a sentinel node useful? There are several uses of it, and the most important one is to replace &lt;code&gt;NULL&lt;/code&gt; for representing a non-existing element. It guards against null pointers.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;NULL&lt;/code&gt; is a very bad design from the very beginning, as it is passed into a function as &lt;code&gt;pointer type&lt;/code&gt; but is not a &lt;code&gt;pointer&lt;/code&gt; at all. Any attempt to call a member function will cause a crush. It is also hard to debug, especially when there are layers of function calls. You cannot dereference a null pointer in debugger; it points to 0x00000000, which has no useful information at all.&lt;/p&gt;
&lt;p&gt;A sentinel &lt;code&gt;nil&lt;/code&gt; on the other hand is a legitimate &lt;code&gt;Node&lt;/code&gt; object. It has all functions supported, and could be more useful for debugging. Debugging-wise, it is printable and assignable.&lt;/p&gt;
&lt;p&gt;It is also used as the parent of &lt;code&gt;root&lt;/code&gt; in our tree. This eliminates the difference between an empty tree and non-empty tree, so insertion and removal of &lt;code&gt;root&lt;/code&gt; could be carried out without an extra conditional branch.&lt;/p&gt;
&lt;h2 id=&#34;codes&#34;&gt;
  Codes
  &lt;a href=&#34;#codes&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;!--  --&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">Production of Sentences and Properties of Languages: Parsing Techniques Notes (2)</title>
    <link rel="alternate">https://powersnail.com/2016/parsing-techniques-notes02/</link>
    <published>Fri, 26 Feb 2016 00:00:00 +0000</published>
    <updated>Fri, 26 Feb 2016 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2016/parsing-techniques-notes02/</id>
    <summary type="html">Generating Sentences ## sentence vs. sentential sentence all symbols belongs to terminals (a valid element of the language) sentential may contain non-terminals, an intermediate form during sentence production Example: #### For a language where $V_N = {P, Q} \land V_T = {a, b, c, d}$, a valid sentential would be $aP$; a valid sentence would be $ac$.</summary>
    <content type="html">&lt;h2 id=&#34;generating-sentences&#34;&gt;
  Generating Sentences
  &lt;a href=&#34;#generating-sentences&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;sentence &lt;em&gt;vs.&lt;/em&gt; sentential&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;sentence&lt;/td&gt;
&lt;td&gt;all symbols belongs to terminals (a valid element of the language)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sentential&lt;/td&gt;
&lt;td&gt;may contain non-terminals, an intermediate form during sentence production&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&#34;example&#34;&gt;
  Example:
  &lt;a href=&#34;#example&#34;&gt;&lt;small&gt;####&lt;/small&gt;&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;For a language where $V_N = {P, Q} \land V_T = {a, b, c, d}$, a valid sentential would be $aP$; a valid sentence would be $ac$.&lt;/p&gt;
&lt;h3 id=&#34;type-0-and-type-1-cs-languages&#34;&gt;
  Type 0 and Type 1 (CS) Languages
  &lt;a href=&#34;#type-0-and-type-1-cs-languages&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Breadth-first Production&lt;/strong&gt;: for each sentential, make copies of it for each applicable rule. Then, repeat the operation on each copy. If there is no &lt;em&gt;non-terminal&lt;/em&gt; in the sentential, it is then a sentence, and could be printed and discarded in the production.&lt;/p&gt;
&lt;p&gt;This process may be infinitely long, but it is guaranteed that an arbitrary sentence will definitely be produced.&lt;/p&gt;
&lt;h4 id=&#34;two-remarks-about-cs-language-sentence-production&#34;&gt;
  Two Remarks about CS Language Sentence Production
  &lt;a href=&#34;#two-remarks-about-cs-language-sentence-production&#34;&gt;&lt;small&gt;####&lt;/small&gt;&lt;/a&gt;
&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;We cannot decide whether a CS language is empty, i.e. whether its rules could produce a sentence. &lt;br&gt; The process takes infinite time, and therefore is &lt;em&gt;undecidable&lt;/em&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It is possible to prove a CS language being non-empty by giving an example of sentence it generates.&lt;/li&gt;
&lt;li&gt;It is impossible to prove a CS language is empty.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;General parsing of CS language is &lt;em&gt;unsolvable&lt;/em&gt;. We cannot produce a list of sentences in a CS language in order by length. Because it is context-sensitive, the length of the sentence could &amp;ldquo;shrink&amp;rdquo; suddenly and unpredictably. &lt;br&gt; As a result, we cannot determine a sentence is not in the language; there is always possibility that it may show up in further production.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Type 0 language has the same properties.&lt;/p&gt;
&lt;h3 id=&#34;type-2-cf-language&#34;&gt;
  Type 2 (CF) Language
  &lt;a href=&#34;#type-2-cf-language&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Monotonic nature of CF language means that the length of sentence will not &amp;ldquo;shrink&amp;rdquo;. Therefore, we could solve the two problems of CS language by a rather simple algorithm:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Scan rules that have terminal on right-hand side,&lt;/li&gt;
&lt;li&gt;marking those as productive;&lt;/li&gt;
&lt;li&gt;scan rules that have productive on right-hand side,&lt;/li&gt;
&lt;li&gt;repeat 2, 3 until meeting the start symbol or no new productive symbols could be found&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If the above process is able to reach the start symbol then it is not empty; otherwise, it finds no way up to the start symbol, the language is empty.&lt;/p&gt;
&lt;p&gt;The length of sentence does not shrink in CF language. Therefore, we could determine a sentence&amp;rsquo;s existence. If we meet the sentence obviously, it belongs to the language. If we keep producing and exceed the length of the sentence, then further production on the sentential will definitely not produce the sentence. We could therefore decide the inclusion of an arbitrary sentence of finite length in finite time.&lt;/p&gt;
&lt;h3 id=&#34;type-3-regular-language&#34;&gt;
  Type 3 (Regular) Language
  &lt;a href=&#34;#type-3-regular-language&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Regular language has rules that right-hand side contains at most one non-terminal, and it should be the rightmost symbol. Regular language could be written as regular expressions that is composed of only terminals and regular operators. As a result, if a non-empty regular expression could be constructed, then the language is non-empty.&lt;/p&gt;
&lt;p&gt;It is also possible to enumerate sentences without breath-first production, as only one non-terminal could be replaced in each sentential. When looking for a sentence $K$ of length $l$, if the length of sentential exceeds $l$, then $K$ cannot be included in the language. Finding any sentence in the process would prove that the language is not empty.&lt;/p&gt;
&lt;!-- page --&gt;
</content>
    <category>posts</category>
  </entry>
  
  <entry>
    <author>
      <name>PowerSnail</name>
    </author>
    <title type="html">Generative Grammar and Four Types of Grammars: Parsing Techniques Notes (1)</title>
    <link rel="alternate">https://powersnail.com/2016/parsing-techniques-notes01/</link>
    <published>Wed, 24 Feb 2016 00:00:00 +0000</published>
    <updated>Wed, 24 Feb 2016 00:00:00 +0000</updated>
    
    <id>https://powersnail.com/2016/parsing-techniques-notes01/</id>
    <summary type="html">Generative Grammar ## There are several views of defining a language. The computer science and formal linguistics perspective:
terms definition Language a set of sentences Sentence a sequence of symbols Alphabet a set of all symbols The semantics - meaning - of a sentence is described by its tokens cooperating with its structure.</summary>
    <content type="html">&lt;h2 id=&#34;generative-grammar&#34;&gt;
  Generative Grammar
  &lt;a href=&#34;#generative-grammar&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;There are several views of defining a language. The computer science and formal linguistics perspective:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;terms&lt;/th&gt;
&lt;th&gt;definition&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Language&lt;/td&gt;
&lt;td&gt;a set of sentences&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sentence&lt;/td&gt;
&lt;td&gt;a &lt;strong&gt;sequence&lt;/strong&gt; of symbols&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Alphabet&lt;/td&gt;
&lt;td&gt;a set of all symbols&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The semantics - meaning - of a sentence is described by its tokens cooperating with its structure.&lt;/p&gt;
&lt;p&gt;Grammar is the set of rules describing a language.
&lt;strong&gt;Generative Grammar&lt;/strong&gt; is&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;exact&lt;/li&gt;
&lt;li&gt;fixed-sized&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;language-can-be-specified-by-infinite-bit-string&#34;&gt;
  Language can be specified by infinite Bit-String
  &lt;a href=&#34;#language-can-be-specified-by-infinite-bit-string&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Sorted Alphabet: $\Sigma$
Language $\Sigma^{* }$ contains all combinations of symbols in $\Sigma$&lt;/p&gt;
&lt;p&gt;The order of sentences in $\Sigma^* $ follows that:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;from length $l = 0$&lt;/em&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Enumerate all combinations that of length $l$&lt;/li&gt;
&lt;li&gt;these combinations are listed according to alphabetical order (lexicographical sorting)&lt;/li&gt;
&lt;li&gt;increment $l$ and repeat from 1.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This will form an infinitely long sorted list. Every language composed by alphabet $\Sigma$ can be identified by choosing from $\Sigma^* $. If we encode this by binary representation, 0 → not including, 1 → including, we can create an infinitely long bit string that indicates every sentence the language contains.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For example:
Language $L = 010010110&amp;hellip;$&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;formal-grammar&#34;&gt;
  Formal Grammar
  &lt;a href=&#34;#formal-grammar&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Recipe of replacing symbols:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Name  -&amp;gt; tom | dick | harry // Name may be replaced by tom, dick or harry
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A grammar is a &lt;em&gt;4-tuple&lt;/em&gt; $(V_N, V_T, R, S)$:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$V_N$ non-terminals, $V_T$ terminals are finite sets of symbols&lt;/li&gt;
&lt;li&gt;$V_N \cap V_T = \varnothing$ terminals and non-terminals cannot have common symbols&lt;/li&gt;
&lt;li&gt;$R$ is the set of rules, a set that contains ordered pairs: ${(P, Q) \mid P\in (V_N\cup V_T)^+ \land Q\in (V_N \cup V_T)^* }$&lt;/li&gt;
&lt;li&gt;$S$ is the start symbol, $S\in V_N$&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;four-types-of-grammars&#34;&gt;
  Four types of Grammars
  &lt;a href=&#34;#four-types-of-grammars&#34;&gt;&lt;small&gt;##&lt;/small&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id=&#34;type-0-phrase-structure-grammar-ps-grammar&#34;&gt;
  Type 0: Phrase Structure Grammar (PS Grammar)
  &lt;a href=&#34;#type-0-phrase-structure-grammar-ps-grammar&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Most freedom. Follows &lt;em&gt;4-tuple&lt;/em&gt; $(V_N, V_T, R, S)$, without further restriction.
Represented as &lt;code&gt;Directed Acyclic Graph&lt;/code&gt;: No cycle exists&lt;/p&gt;
&lt;h3 id=&#34;type-1-context-sensitive-grammar-cs-grammar&#34;&gt;
  Type 1: Context-Sensitive Grammar (CS Grammar)
  &lt;a href=&#34;#type-1-context-sensitive-grammar-cs-grammar&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;There are two equivalent definitions: &lt;code&gt;Monotonic&lt;/code&gt; and &lt;code&gt;Context-Sensitive&lt;/code&gt;.
Can be represented by a DAG, similar to PS Grammar.&lt;/p&gt;
&lt;h4 id=&#34;monotonic&#34;&gt;
  Monotonic
  &lt;a href=&#34;#monotonic&#34;&gt;&lt;small&gt;####&lt;/small&gt;&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;For each rule, left-hand side has more or equal number of symbols to right-hand side.&lt;/p&gt;
&lt;h4 id=&#34;context-sensitive&#34;&gt;
  Context-Sensitive
  &lt;a href=&#34;#context-sensitive&#34;&gt;&lt;small&gt;####&lt;/small&gt;&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;Every rule is context-sensitive.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Left-hand side contains only one symbol to be changed in the right-hand side.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;type-2-context-free-grammar-cf-grammar&#34;&gt;
  Type 2: Context-Free Grammar (CF Grammar)
  &lt;a href=&#34;#type-2-context-free-grammar-cf-grammar&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;LHS could only contain one non-terminal symbol. (Thus not related to neighboring symbols).
Represented by a tree, as branches of a node is not relevant to other nodes.&lt;/p&gt;
&lt;p&gt;The generative power of CF Grammar comes from two operations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Concatenation&lt;/li&gt;
&lt;li&gt;Choice (choosing from one of the alternatives in the RHS)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;NT -&amp;gt; tom | NT dick | ...&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;type-3-regular-grammar&#34;&gt;
  Type 3: Regular Grammar
  &lt;a href=&#34;#type-3-regular-grammar&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Mostly referring to &lt;code&gt;right regular grammar&lt;/code&gt;.
Each rule could only contain one non-terminal, as the rightmost item.
Represented by a list, because each sentential has only one replaceable item (non-terminal), or in a production chain.&lt;/p&gt;
&lt;p&gt;All regular grammar can be expressed in a regular expression, which sufficiently equal to all rules in the grammar.&lt;/p&gt;
&lt;p&gt;Regular Expression Notation Styles:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Notation&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;$^{+ }$&lt;/td&gt;
&lt;td&gt;One or more instances of the left-adjacent item&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$^{* }$&lt;/td&gt;
&lt;td&gt;Zero or more instances of the left-adjacent item&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$^{? }$&lt;/td&gt;
&lt;td&gt;Zero or one instance of the left-adjacent item&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$[abc]$&lt;/td&gt;
&lt;td&gt;Choosing one from $(a, b, c)$, i.e., $(a\mid b\mid c)$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;p&gt;$S_S\to(([tdh],)^{* }[tdh] &amp;amp; )^{? }[tdh]$&lt;/p&gt;
&lt;h3 id=&#34;type-4-finite-choice-grammar-fc-grammar&#34;&gt;
  Type 4: Finite Choice Grammar (FC Grammar)
  &lt;a href=&#34;#type-4-finite-choice-grammar-fc-grammar&#34;&gt;&lt;small&gt;###&lt;/small&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Each rule could have only terminals in right-hand side.
Very limited expressive power.&lt;/p&gt;
</content>
    <category>posts</category>
  </entry>
  
</feed>
