<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://ulysseszh.github.io/feed/tags/ruby.xml" rel="self" type="application/atom+xml" /><link href="https://ulysseszh.github.io/" rel="alternate" type="text/html" hreflang="en-US" /><updated>2026-04-30T17:49:58-07:00</updated><id>https://ulysseszh.github.io/feed/tags/ruby.xml</id><title type="html"><![CDATA[Ulysses’ trip]]></title><subtitle>Here we are at the awesome (awful) blog written by UlyssesZhan!</subtitle><author><name>UlyssesZhan</name><email>ulysseszhan@gmail.com</email></author><entry><title type="html"><![CDATA[An 🎃 easy 👻 but 🍬 <em>spooky</em> 💀 Ruby challenge]]></title><link href="https://ulysseszh.github.io/programming/2023/10/31/ruby-spooky-challenge.html" rel="alternate" type="text/html" title="An 🎃 easy 👻 but 🍬 spooky 💀 Ruby challenge" /><published>2023-10-31T17:30:48-07:00</published><updated>2023-10-31T17:30:48-07:00</updated><id>https://ulysseszh.github.io/programming/2023/10/31/ruby-spooky-challenge</id><content type="html" xml:base="https://ulysseszh.github.io/programming/2023/10/31/ruby-spooky-challenge.html"><![CDATA[<p>This was a challenge in the <a href="https://discord.gg/ad2acQFtkh" target="_blank" rel="external">Ruby Discord server</a>. The contents of the challenge is:<sup>©</sup></p>
<!-- markdownlint-disable line-length blanks-around-fences fenced-code-language no-trailing-spaces -->
<blockquote>
<h2 id="halloween-challenge" data-label="0.1">Halloween Challenge</h2>
<p>It’s the weekend and you’ve just completed a seance with friends. After communing with the dead, you realize a mysterious message was left behind.</p>
<table class="rouge-table"><tbody><tr><td class="highlight language-plaintext"><pre><code><span class="line line-1">3🍬4🎃04🎃6👻00🎃62🎃6👻32👻5🎃4🍬42🎃4🎃2🎃6🍬3🎃52🍬3🎃6💀0🎃2🎃6🍬13🍬0🎃432👻4👻4🎃230🎃62🎃1🍬03🎃2🍬6
</span><span class="line line-2">🍬4👻5👻3🎃220🎃5👻0👻5🎃4🎃6👻42🎃4👻01🎃60🍬1🎃2👻3👻30🎃6💀0👻0🍬3🎃5👻0👻5🎃6👻0🍬30🎃61🍬0🎃1🎃2🎃6🎃42👻3🍬03🎃2💀3
</span><span class="line line-3">🎃0🎃2👻5🎃22🍬3🎃5🎃6🍬3🎃5🎃2🎃6🎃52🍬4👻5🍬3🎃2🎃1🎃6👻4🍬0🍬0👻5🍬6🎃6👻0🍬30🎃604👻5🍬32💀1🎃6💀0🎃2🎃6🎃2💀1🍬1👻3🍬03🎃2🍬6
</span><span class="line line-4">4🎃2🍬3🎃6👻0👻5🎃6🍬3🎃5🎃2🎃6💀0🍬03👻3🎃1🎃6🍬0🎃3🎃6🍬13🍬0🎃432👻4👻4👻0👻5🎃4🍬6🎃6👻0🍬3🎃6🍬3🎃53👻0🍬5🎃20🎃6🎃2🍬5🎃2👻5🎃6👻4🍬03🎃2💀3
</span><span class="line line-5">
</span><span class="line line-6">👻0👻5🎃6🍬3🎃5🎃2🎃6134🍬1🍬3👻01🎃6👻4🎃2🍬3🎃5🍬0🎃10🍬6🎃6💀0🎃5🎃23🎃2🎃6🎃2🎃23👻0🎃2🎃6🎃0🍬4🎃40🎃6👻424🎃6🍬33🎃22🎃1🍬6
</span><span class="line line-7">0👻2🎃2👻3🎃2🍬3🍬0👻50🎃6🍬0🎃3🎃6🎃233🍬030🎃6👻0👻5🎃6🍬3🎃5🎃2🎃6🎃123👻2🎃623🎃2🎃6💀0👻0🎃1🎃20🍬13🎃22🎃1💀3
</span><span class="line line-8">
</span><span class="line line-9">👻5🍬0🍬3🎃62🎃6👻32👻5🎃4🍬42🎃4🎃2🎃6🍬0🎃3🎃6🍬3🎃5🎃2🎃6🍬120🍬3🍬6🎃6🎃0🍬4🍬3🎃6🍬0👻5🎃2🎃6💀0🎃2🎃6🎃5🍬0👻3🎃1🎃6🍬0🍬43🎃6🎃5🎃22🎃10🍬6
</span><span class="line line-10">🍬0🍬5🎃23🎃61🍬0🍬4👻5🍬3👻3🎃200🎃6🍬13🍬0👻1🎃21🍬30🍬6🎃6💀0🎃5🎃23🎃2🎃6👻0🍬30🎃6🍬1🍬0💀0🎃23🎃6🎃520🎃60🍬13🎃22🎃1💀3
</span><span class="line line-11">🍬3🎃5🎃2🎃6🍬33👻01👻20🎃62👻5🎃1🎃6🍬33🎃22🍬30🎃6🍬0🎃3🎃63🍬4🎃04🍬6🎃6👻3👻0👻2🎃2🎃6💀0👻0🍬31🎃5🎃20👻6🎃61🎃523👻40🍬6🎃61🍬0👻5🍬5🎃2👻5🎃2🍬6
</span><span class="line line-12">
</span><span class="line line-13">🎃132💀0👻0👻5🎃4🎃6🍬40🎃6👻0👻5🍬3🍬0🎃6👻0🍬30🎃6💀0🍬03👻3🎃1🍬6🎃6💀0🎃5🎃23🎃2🎃6🍬3🎃5🎃2🎃60🍬4🎃0👻3👻0👻4🎃2🎃6👻00🎃60🎃2🎃2👻5💀3
</span><span class="line line-14">🎃2👻51🎃52👻5🍬3👻0👻5🎃4🎃6🍬40🎃6💀0👻0🍬3🎃5🎃6🎃4🎃2👻40🍬6🎃6👻0🍬3👻60🎃6🎃2🍬5🎃234🎃61🍬0🎃1🎃23👻60🎃6🎃13🎃22👻4🍬6
</span><span class="line line-15">2🎃1🍬5🎃2👻5🍬3🍬43🎃20🎃6👻0👻5🎃6🍬3🎃5🎃2🎃61🍬0🎃1🎃2🍬6🎃6💀0🎃5🎃23🎃2🎃6🍬3🎃5🎃2🎃6🎃2🎃23👻0🎃2👻60🎃63🍬0🍬4🍬3👻0👻5🎃2💀3
</span><span class="line line-16">🎃1🎃22🍬3🎃5🎃6👻424🎃60🎃2🎃2👻4🎃6🍬3🍬0🎃6👻3🍬43👻2🍬6🎃6🎃0🍬4🍬3🎃6🎃3🍬03🎃63🍬4🎃04🎃6👻0🍬3👻60🎃6🎃52👻3👻3🍬0💀0🎃2🎃2👻56
</span></code></pre></td></tr></tbody></table>
<p>However, with your unique Ouija board you should have no problem deciphering what they left!</p>
<h3 id="objective" data-label="0.1.1">Objective</h3>
<p>Your Ouija board looks like the following <a href="https://en.wikipedia.org/wiki/Straddling_checkerboard" target="_blank" rel="external">straddling checkerboard</a>:</p>
<table class="rouge-table"><tbody><tr><td class="highlight language-plaintext"><pre><code><span class="line line-1">==================================
</span><span class="line line-2">|    | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
</span><span class="line line-3">|    | S | C | A | R | Y | ? | ! |
</span><span class="line line-4">| 🎃 | B | D | E | F | G | H |   |
</span><span class="line line-5">| 👻 | I | J | K | L | M | N | ' |
</span><span class="line line-6">| 🍬 | O | P | Q | T | U | V | , |
</span><span class="line line-7">| 💀 | W | X | Z | . | # | $ | : |
</span><span class="line line-8">==================================
</span></code></pre></td></tr></tbody></table>
<p>Use your Ruby skills and the board above to decrypt the message. I have attached a file to help get you started. You don’t need to use it if you don’t want to.</p>
<p>You may also find this <a href="https://www.ciphermachinesandcryptology.com/en/table.htm" target="_blank" rel="external">link</a> helpful too.</p>
<h3 id="requirements" data-label="0.1.2">Requirements</h3>
<ul>
<li>Must use Ruby</li>
<li>Decrypt the message</li>
<li><strong>Determine the hidden message <em>within</em> the decrypted message</strong></li>
</ul>
<!-- markdownlint-enable line-length blanks-around-fences fenced-code-language no-trailing-spaces -->
</blockquote>
<h2 data-label="0.2" id="my-solution">My solution</h2>
<p>I am too stupid to think of regular expressions at first, so I wrote this:</p>
<!-- markdownlint-disable line-length -->
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="s2">" 0123456</span><span class="se">\n</span><span class="s2"> SCARY?!</span><span class="se">\n</span><span class="s2">🎃BDEFGH </span><span class="se">\n</span><span class="s2">👻IJKLMN'</span><span class="se">\n</span><span class="s2">🍬OPQTUV,</span><span class="se">\n</span><span class="s2">💀WXZ.</span><span class="se">\#</span><span class="s2">$:"</span><span class="p">.</span><span class="nf">split</span><span class="p">(</span><span class="sc">?\n</span><span class="p">).</span><span class="nf">map</span><span class="p">(</span><span class="o">&amp;</span><span class="ss">:chars</span><span class="p">).</span><span class="nf">tap</span><span class="p">{</span><span class="o">|</span><span class="n">b</span><span class="o">|&lt;&lt;</span><span class="no">M</span><span class="p">.</span><span class="nf">chars</span><span class="p">.</span><span class="nf">reduce</span><span class="p">(</span><span class="kp">nil</span><span class="p">){</span><span class="o">|</span><span class="n">r</span><span class="p">,</span><span class="n">e</span><span class="o">|</span><span class="n">e</span><span class="o">==</span><span class="sc">?\n</span><span class="p">?</span><span class="nb">print</span><span class="p">(</span><span class="n">e</span><span class="p">):</span> <span class="n">r</span> <span class="p">?</span><span class="nb">print</span><span class="p">(</span><span class="n">b</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">b</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nf">index</span> <span class="n">e</span><span class="p">]):</span> <span class="n">b</span><span class="p">.</span><span class="nf">index</span><span class="p">{</span><span class="n">_1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">==</span><span class="n">e</span><span class="p">}</span><span class="o">||</span><span class="nb">print</span><span class="p">(</span><span class="n">b</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="n">b</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nf">index</span> <span class="n">e</span><span class="p">])}}</span>
</span>
            <span class="line line-2"><span class="sh">3🍬4🎃04...</span>
</span>
            <span class="line line-3"><span class="no">M</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<!-- markdownlint-enable line-length -->
<p class="no-indent">
I did not want to code golf, but I did intend to wrote a one-liner. It seems hard to understand, but it is pretty straightforward if it is expanded:
</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="n">board</span> <span class="o">=</span> <span class="p">[</span><span class="s1">' '</span><span class="p">,</span> <span class="s1">'0'</span><span class="p">,</span> <span class="s1">'1'</span><span class="p">,</span> <span class="s1">'2'</span><span class="p">,</span> <span class="s1">'3'</span><span class="p">,</span> <span class="s1">'4'</span><span class="p">,</span> <span class="s1">'5'</span><span class="p">,</span> <span class="s1">'6'</span><span class="p">],</span>
</span>
            <span class="line line-2">        <span class="p">[</span><span class="s1">' '</span><span class="p">,</span> <span class="s1">'S'</span><span class="p">,</span> <span class="s1">'C'</span><span class="p">,</span> <span class="s1">'A'</span><span class="p">,</span> <span class="s1">'R'</span><span class="p">,</span> <span class="s1">'Y'</span><span class="p">,</span> <span class="s1">'?'</span><span class="p">,</span> <span class="s1">'!'</span><span class="p">],</span>
</span>
            <span class="line line-3">        <span class="p">[</span><span class="s1">'🎃'</span><span class="p">,</span> <span class="s1">'B'</span><span class="p">,</span> <span class="s1">'D'</span><span class="p">,</span> <span class="s1">'E'</span><span class="p">,</span> <span class="s1">'F'</span><span class="p">,</span> <span class="s1">'G'</span><span class="p">,</span> <span class="s1">'H'</span><span class="p">,</span> <span class="s1">' '</span><span class="p">],</span>
</span>
            <span class="line line-4">        <span class="p">[</span><span class="s1">'👻'</span><span class="p">,</span> <span class="s1">'I'</span><span class="p">,</span> <span class="s1">'J'</span><span class="p">,</span> <span class="s1">'K'</span><span class="p">,</span> <span class="s1">'L'</span><span class="p">,</span> <span class="s1">'M'</span><span class="p">,</span> <span class="s1">'N'</span><span class="p">,</span> <span class="s2">"'"</span><span class="p">],</span>
</span>
            <span class="line line-5">        <span class="p">[</span><span class="s1">'🍬'</span><span class="p">,</span> <span class="s1">'O'</span><span class="p">,</span> <span class="s1">'P'</span><span class="p">,</span> <span class="s1">'Q'</span><span class="p">,</span> <span class="s1">'T'</span><span class="p">,</span> <span class="s1">'U'</span><span class="p">,</span> <span class="s1">'V'</span><span class="p">,</span> <span class="s1">','</span><span class="p">],</span>
</span>
            <span class="line line-6">        <span class="p">[</span><span class="s1">'💀'</span><span class="p">,</span> <span class="s1">'W'</span><span class="p">,</span> <span class="s1">'X'</span><span class="p">,</span> <span class="s1">'Z'</span><span class="p">,</span> <span class="s1">'.'</span><span class="p">,</span> <span class="s1">'#'</span><span class="p">,</span> <span class="s1">'$'</span><span class="p">,</span> <span class="s1">':'</span><span class="p">]</span>
</span>
            <span class="line line-7"><span class="n">message</span> <span class="o">=</span> <span class="o">&lt;&lt;</span><span class="no">MESSAGE</span>
</span>
            <span class="line line-8"><span class="sh">3🍬4🎃04...</span>
</span>
            <span class="line line-9"><span class="no">MESSAGE</span>
</span>
            <span class="line line-10">
</span>
            <span class="line line-11"><span class="n">message</span><span class="p">.</span><span class="nf">chars</span><span class="p">.</span><span class="nf">reduce</span> <span class="kp">nil</span> <span class="k">do</span> <span class="o">|</span><span class="n">row</span><span class="p">,</span> <span class="n">encoded_char</span><span class="o">|</span>
</span>
            <span class="line line-12">	<span class="k">if</span> <span class="n">encoded_char</span> <span class="o">==</span> <span class="sc">?\n</span> <span class="c1"># newline in the message</span>
</span>
            <span class="line line-13">		<span class="nb">print</span> <span class="n">encoded_char</span>
</span>
            <span class="line line-14">	<span class="k">elsif</span> <span class="n">row</span> <span class="c1"># last char is an emoji, corresponding to a row in the board</span>
</span>
            <span class="line line-15">		<span class="nb">print</span> <span class="n">board</span><span class="p">[</span><span class="n">row</span><span class="p">][</span><span class="n">board</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nf">index</span> <span class="n">encoded_char</span><span class="p">]</span>
</span>
            <span class="line line-16">		<span class="kp">nil</span>
</span>
            <span class="line line-17">	<span class="k">elsif</span> <span class="n">new_row</span> <span class="o">=</span> <span class="n">board</span><span class="p">.</span><span class="nf">index</span> <span class="p">{</span> <span class="n">_1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="n">encoded_char</span> <span class="p">}</span>
</span>
            <span class="line line-18">		<span class="n">new_row</span>
</span>
            <span class="line line-19">	<span class="k">else</span>
</span>
            <span class="line line-20">		<span class="nb">print</span> <span class="n">board</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="n">board</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nf">index</span> <span class="n">encoded_char</span><span class="p">]</span>
</span>
            <span class="line line-21">		<span class="kp">nil</span>
</span>
            <span class="line line-22">	<span class="k">end</span>
</span>
            <span class="line line-23"><span class="k">end</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p>Then, I realized that I could have used regular expressions, so I wrote a cleaner version:</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="nb">puts</span> <span class="o">&lt;&lt;</span><span class="no">M</span><span class="p">.</span><span class="nf">gsub</span><span class="p">(</span><span class="sr">/([🎃👻🍬💀])?([0-6])/</span><span class="p">){</span><span class="o">|</span><span class="n">s</span><span class="o">|</span><span class="p">{</span><span class="kp">nil</span><span class="o">=&gt;</span><span class="s1">'SCARY?!'</span><span class="p">,</span><span class="err">🎃</span><span class="ss">:'BDEFGH '</span><span class="p">,</span><span class="err">👻</span><span class="ss">:"IJKLMN'"</span><span class="p">,</span><span class="err">🍬</span><span class="ss">:'OPQTUV,'</span><span class="p">,</span><span class="err">💀</span><span class="ss">:'WXZ.#$:'</span><span class="p">}[</span><span class="vg">$1</span><span class="o">&amp;</span><span class="p">.</span><span class="nf">to_sym</span><span class="p">][</span><span class="vg">$2</span><span class="p">.</span><span class="nf">to_i</span><span class="p">]}</span>
</span>
            <span class="line line-2"><span class="sh">3🍬4🎃04...</span>
</span>
            <span class="line line-3"><span class="no">M</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p>Then, I suddenly become creative and realized that I can use another regular expression to implement a string-based indexing, and that I can use <code>-p</code> option of Ruby command line to save even more characters (here I smelled code golfing):</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="c1">#!/usr/bin/env ruby -p</span>
</span>
            <span class="line line-2"><span class="nb">gsub</span><span class="p">(</span><span class="sr">/(\D?)(\d)/</span><span class="p">){</span><span class="s1">'SCARY?!🎃BDEFGH 👻IJKLMN\'🍬OPQTUV,💀WXZ.#$:'</span><span class="p">[</span><span class="sr">/#$1.{#$2}(.)/</span><span class="p">,</span><span class="mi">1</span><span class="p">]}</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p>Here are some <a href="https://gist.github.com/ParadoxV5/77cab0e2b47004712deba623fe5ea816" target="_blank" rel="external">other solutions</a>. Check them out!</p>
<h3 data-label="0.2.1" id="some-explanations-for-the-code-golf-solution">Some explanations for the code golf solution</h3>
<ul>
<li>The <code>-p</code> option basically wraps the code in a <code>while gets</code> loop, and you can access the current line with <code>$_</code>. Ruby will output the contents of <code>$_</code> after each iteration.</li>
<li>The method <code>Kernel#gsub</code> modifies <code>$_</code> (the current processing input line). It is only available when running Ruby with <code>-p</code> option.</li>
<li>The method <code>String#[]</code> returns a substring. What is good about this method is that, if you use a regular expression to find the substring, you can use the second argument to specify which capture group in the regular expression you want to return.</li>
<li>In a string literal, you can use <code>#$some_global_variable</code> as a shortcut of <code>#{$some_global_variable}</code>. This is also true for instance variables and class variables.</li>
</ul>
<h2 data-label="0.3" id="the-message">The message</h2>
<p>The decoded message is:<sup>©</sup></p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-plaintext">
        <pre>
          <code>
            <span class="line line-1">RUBY IS A LANGUAGE THAT WE PROGRAMMERS ADORE,
</span>
            <span class="line line-2">UNLEASHING MAGIC SPELLS WITHIN ITS CODE GALORE.
</span>
            <span class="line line-3">BENEATH THE HAUNTED MOON, ITS SYNTAX WE EXPLORE,
</span>
            <span class="line line-4">YET IN THE WORLD OF PROGRAMMING, IT THRIVES EVEN MORE.
</span>
            <span class="line line-5">
</span>
            <span class="line line-6">IN THE CRYPTIC METHODS, WHERE EERIE BUGS MAY TREAD,
</span>
            <span class="line line-7">SKELETONS OF ERRORS IN THE DARK ARE WIDESPREAD.
</span>
            <span class="line line-8">
</span>
            <span class="line line-9">NOT A LANGUAGE OF THE PAST, BUT ONE WE HOLD OUR HEADS,
</span>
            <span class="line line-10">OVER COUNTLESS PROJECTS, WHERE ITS POWER HAS SPREAD.
</span>
            <span class="line line-11">THE TRICKS AND TREATS OF RUBY, LIKE WITCHES' CHARMS, CONVENE,
</span>
            <span class="line line-12">
</span>
            <span class="line line-13">DRAWING US INTO ITS WORLD, WHERE THE SUBLIME IS SEEN.
</span>
            <span class="line line-14">ENCHANTING US WITH GEMS, IT'S EVERY CODER'S DREAM,
</span>
            <span class="line line-15">ADVENTURES IN THE CODE, WHERE THE EERIE'S ROUTINE.
</span>
            <span class="line line-16">DEATH MAY SEEM TO LURK, BUT FOR RUBY IT'S HALLOWEEN!
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p class="no-indent">
Did you spot the hidden message?
</p>]]></content><author><name>UlyssesZhan</name><email>ulysseszhan@gmail.com</email></author><category term="programming" /><category term="ruby" /><category term="code golf" /><category term="fooling around" /><summary type="html"><![CDATA[“It’s the weekend and you’ve just completed a seance with friends. After communing with the dead, you realize a mysterious message was left behind.” What is the decoded message? Use your Ruby skills to find out!]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://ulysseszh.github.io/assets/images/covers/2023-10-31-ruby-spooky-challenge.png" /><media:content medium="image" url="https://ulysseszh.github.io/assets/images/covers/2023-10-31-ruby-spooky-challenge.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html"><![CDATA[The distribution when indistinguishable balls are put into boxes]]></title><link href="https://ulysseszh.github.io/math/2023/05/09/stars-bars-geometric.html" rel="alternate" type="text/html" title="The distribution when indistinguishable balls are put into boxes" /><published>2023-05-09T12:19:26-07:00</published><updated>2023-05-09T12:19:26-07:00</updated><id>https://ulysseszh.github.io/math/2023/05/09/stars-bars-geometric</id><content type="html" xml:base="https://ulysseszh.github.io/math/2023/05/09/stars-bars-geometric.html"><![CDATA[<blockquote>
<p>If there are 200 typographical errors randomly distributed in a 500 page manuscript, find the probability that a given page contains exactly 3 errors.</p>
</blockquote>
<p class="no-indent">
We can abstract this type of problems as follows:
</p>
<blockquote>
Suppose there are <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span></span> distinguishable boxes and <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi></mrow><annotation encoding="application/x-tex">k</annotation></semantics></math></span></span> indistinguishable balls. Now, we randomly put the balls into the boxes. For each of the boxes, what is the probability that it contains <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span></span> balls?
</blockquote>
<p class="no-indent">
For example, if the first page contains 3 errors, the second page contains 197 errors, and the rest of the pages contain no errors, then the situation corresponds to the situation where the first box contains 3 balls, the second box contains 197 balls, and the rest of the boxes contain no balls. The balls are indistinguishable because we can only determine how many errors are on each page but not which errors are on the page.
</p>
<p>To deal with the problem, we simply need to find these two numbers:</p>
<ul>
<li>the number of ways to put <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi></mrow><annotation encoding="application/x-tex">k</annotation></semantics></math></span></span> indistinguishable balls into <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span></span> distinguishable boxes, and</li>
<li>the number of ways to put <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi><mo>−</mo><mi>m</mi></mrow><annotation encoding="application/x-tex">k-m</annotation></semantics></math></span></span> indistinguishable balls into <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>−</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">n-1</annotation></semantics></math></span></span> distinguishable boxes.</li>
</ul>
<p class="no-indent">
The latter corresponds to the number of ways to put the balls into the boxes provided that we already know that the given box contains <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span></span> balls. After we find these two numbers, their ratio is the probability in question.
</p>
<p>To find the number of ways to put <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi></mrow><annotation encoding="application/x-tex">k</annotation></semantics></math></span></span> indistinguishable balls into <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span></span> distinguishable boxes, we can use the stars and bars method. To see this, we write a special example. Here is an example of <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>=</mo><mn>4</mn></mrow><annotation encoding="application/x-tex">n=4</annotation></semantics></math></span></span> and <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi><mo>=</mo><mn>6</mn></mrow><annotation encoding="application/x-tex">k=6</annotation></semantics></math></span></span>: <span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mrow/><mi mathvariant="normal">∣</mi><mrow/><mo>⋆</mo><mrow/><mo>⋆</mo><mrow/><mi mathvariant="normal">∣</mi><mrow/><mo>⋆</mo><mrow/><mi mathvariant="normal">∣</mi><mrow/><mo>⋆</mo><mrow/><mo>⋆</mo><mrow/><mo>⋆</mo><mrow/><mo separator="true">,</mo></mrow><annotation encoding="application/x-tex">{}|{}\star{}\star{}|{}\star{}|{}\star{}\star{}\star{},</annotation></semantics></math></span></span></span> which corresponds to the distribution <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0</mn><mo separator="true">,</mo><mn>2</mn><mo separator="true">,</mo><mn>1</mn><mo separator="true">,</mo><mn>3</mn></mrow><annotation encoding="application/x-tex">0,2,1,3</annotation></semantics></math></span></span>. We can see that there are <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>−</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">n-1</annotation></semantics></math></span></span> bars and <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi></mrow><annotation encoding="application/x-tex">k</annotation></semantics></math></span></span> stars. Therefore, the number of ways to put the balls is the same as the number of ways to choose the <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi></mrow><annotation encoding="application/x-tex">k</annotation></semantics></math></span></span> positions of the stars among <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>+</mo><mi>k</mi><mo>−</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">n+k-1</annotation></semantics></math></span></span> positions. Therefore, the number of ways is
<span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msub><mi>N</mi><mrow><mi>n</mi><mo separator="true">,</mo><mi>k</mi></mrow></msub><mo>=</mo><mrow><mo fence="true">(</mo><mfrac linethickness="0px"><mrow><mi>n</mi><mo>+</mo><mi>k</mi><mo>−</mo><mn>1</mn></mrow><mi>k</mi></mfrac><mo fence="true">)</mo></mrow><mo>=</mo><mfrac><mrow><mrow><mo fence="true">(</mo><mi>n</mi><mo>+</mo><mi>k</mi><mo>−</mo><mn>1</mn><mo fence="true">)</mo></mrow><mo stretchy="false">!</mo></mrow><mrow><mi>k</mi><mo stretchy="false">!</mo><mrow><mo fence="true">(</mo><mi>n</mi><mo>−</mo><mn>1</mn><mo fence="true">)</mo></mrow><mo stretchy="false">!</mo></mrow></mfrac><mi mathvariant="normal">.</mi></mrow><annotation encoding="application/x-tex">N_{n,k}=\binom{n+k-1}{k}=\frac{\left(n+k-1\right)!}{k!\left(n-1\right)!}.</annotation></semantics></math></span></span></span> Therefore, the final probability of the given box containing <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span></span> balls is <span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msub><mi>P</mi><mrow><mi>n</mi><mo separator="true">,</mo><mi>k</mi></mrow></msub><mo stretchy="false">(</mo><mi>m</mi><mo stretchy="false">)</mo><mo>=</mo><mfrac><msub><mi>N</mi><mrow><mi>n</mi><mo>−</mo><mn>1</mn><mo separator="true">,</mo><mi>k</mi><mo>−</mo><mi>m</mi></mrow></msub><msub><mi>N</mi><mrow><mi>n</mi><mo separator="true">,</mo><mi>k</mi></mrow></msub></mfrac><mo>=</mo><mfrac><mrow><mrow><mo fence="true">(</mo><mi>n</mi><mo>−</mo><mn>1</mn><mo fence="true">)</mo></mrow><mi>k</mi><mo stretchy="false">!</mo><mrow><mo fence="true">(</mo><mi>n</mi><mo>+</mo><mi>k</mi><mo>−</mo><mi>m</mi><mo>−</mo><mn>2</mn><mo fence="true">)</mo></mrow><mo stretchy="false">!</mo></mrow><mrow><mrow><mo fence="true">(</mo><mi>k</mi><mo>−</mo><mi>m</mi><mo fence="true">)</mo></mrow><mo stretchy="false">!</mo><mrow><mo fence="true">(</mo><mi>n</mi><mo>+</mo><mi>k</mi><mo>−</mo><mn>1</mn><mo fence="true">)</mo></mrow><mo stretchy="false">!</mo></mrow></mfrac><mi mathvariant="normal">.</mi></mrow><annotation encoding="application/x-tex">P_{n,k}(m)=\frac{N_{n-1,k-m}}{N_{n,k}}
=\frac{\left(n-1\right)k!\left(n+k-m-2\right)!}{\left(k-m\right)!\left(n+k-1\right)!}.</annotation></semantics></math></span></span></span></p>
<hr/>
<p>Another easy way to derive this result is by using the generating function. The number <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>N</mi><mrow><mi>n</mi><mo separator="true">,</mo><mi>k</mi></mrow></msub></mrow><annotation encoding="application/x-tex">N_{n,k}</annotation></semantics></math></span></span> is just the coefficient of <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>x</mi><mi>k</mi></msup></mrow><annotation encoding="application/x-tex">x^k</annotation></semantics></math></span></span> in the expansion of the generating function <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mrow><mo fence="true">(</mo><mn>1</mn><mo>+</mo><mi>x</mi><mo>+</mo><msup><mi>x</mi><mn>2</mn></msup><mo>+</mo><mo>⋯</mo><mtext> </mtext><mo fence="true">)</mo></mrow><mi>n</mi></msup></mrow><annotation encoding="application/x-tex">\left(1+x+x^2+\cdots\right)^n</annotation></semantics></math></span></span>. The generating function is just <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mrow><mo fence="true">(</mo><mn>1</mn><mo>−</mo><mi>x</mi><mo fence="true">)</mo></mrow><mrow><mo>−</mo><mi>n</mi></mrow></msup></mrow><annotation encoding="application/x-tex">\left(1-x\right)^{-n}</annotation></semantics></math></span></span>, which can be easily expanded by using the binomial theorem.</p>
<hr/>
<p>We are now interested in the limit <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo separator="true">,</mo><mi>k</mi><mo>→</mo><mi mathvariant="normal">∞</mi></mrow><annotation encoding="application/x-tex">n,k\to\infty</annotation></semantics></math></span></span> with <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>λ</mi><mo><mi mathvariant="normal">≔</mi></mo><mi>k</mi><mi mathvariant="normal">/</mi><mi>n</mi></mrow><annotation encoding="application/x-tex">\lambda\coloneqq k/n</annotation></semantics></math></span></span> fixed. By Stirling’s approximation, we have <span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msub><mi>P</mi><mrow><mi>n</mi><mo separator="true">,</mo><mi>k</mi></mrow></msub><mo stretchy="false">(</mo><mi>m</mi><mo stretchy="false">)</mo><mo>∼</mo><mrow><mo fence="true">(</mo><mi>n</mi><mo>−</mo><mn>1</mn><mo fence="true">)</mo></mrow><mfrac><mrow><msup><mi>k</mi><mrow><mi>k</mi><mo>+</mo><mn>1</mn><mi mathvariant="normal">/</mi><mn>2</mn></mrow></msup><msup><mrow><mo fence="true">(</mo><mi>n</mi><mo>+</mo><mi>k</mi><mo>−</mo><mi>m</mi><mo>−</mo><mn>2</mn><mo fence="true">)</mo></mrow><mrow><mi>n</mi><mo>+</mo><mi>k</mi><mo>−</mo><mi>m</mi><mo>−</mo><mn>2</mn><mo>+</mo><mn>1</mn><mi mathvariant="normal">/</mi><mn>2</mn></mrow></msup></mrow><mrow><msup><mrow><mo fence="true">(</mo><mi>k</mi><mo>−</mo><mi>m</mi><mo fence="true">)</mo></mrow><mrow><mi>k</mi><mo>−</mo><mi>m</mi><mo>+</mo><mn>1</mn><mi mathvariant="normal">/</mi><mn>2</mn></mrow></msup><msup><mrow><mo fence="true">(</mo><mi>n</mi><mo>+</mo><mi>k</mi><mo>−</mo><mn>1</mn><mo fence="true">)</mo></mrow><mrow><mi>n</mi><mo>+</mo><mi>k</mi><mo>−</mo><mn>1</mn><mo>+</mo><mn>1</mn><mi mathvariant="normal">/</mi><mn>2</mn></mrow></msup></mrow></mfrac><msup><mi mathvariant="normal">e</mi><mrow><mi>k</mi><mo>−</mo><mi>m</mi><mo>+</mo><mi>n</mi><mo>+</mo><mi>k</mi><mo>−</mo><mn>1</mn><mo>−</mo><mi>k</mi><mo>−</mo><mi>n</mi><mo>−</mo><mi>k</mi><mo>+</mo><mi>m</mi><mo>+</mo><mn>2</mn></mrow></msup><mi mathvariant="normal">.</mi></mrow><annotation encoding="application/x-tex">P_{n,k}(m)\sim\left(n-1\right)
\frac{k^{k+1/2}\left(n+k-m-2\right)^{n+k-m-2+1/2}}{\left(k-m\right)^{k-m+1/2}\left(n+k-1\right)^{n+k-1+1/2} }
\mathrm e^{k-m+n+k-1-k-n-k+m+2}.</annotation></semantics></math></span></span></span> The <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mi mathvariant="normal">/</mi><mn>2</mn></mrow><annotation encoding="application/x-tex">1/2</annotation></semantics></math></span></span>’s in the exponents can just be dropped because you may find that if we extract the <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mi mathvariant="normal">/</mi><mn>2</mn></mrow><annotation encoding="application/x-tex">1/2</annotation></semantics></math></span></span>’s, the factor tends to unity. The exponential is just constant <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">e</mi></mrow><annotation encoding="application/x-tex">\mathrm e</annotation></semantics></math></span></span>. Therefore, we have
<span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mtable rowspacing="0.25em" columnalign="right left" columnspacing="0em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><msub><mi>P</mi><mrow><mi>n</mi><mo separator="true">,</mo><mi>k</mi></mrow></msub><mo stretchy="false">(</mo><mi>m</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow/><mo>∼</mo><mrow><mo fence="true">(</mo><mi>n</mi><mo>−</mo><mn>1</mn><mo fence="true">)</mo></mrow><mfrac><mrow><msup><mrow><mo fence="true">(</mo><mi>λ</mi><mi>n</mi><mo fence="true">)</mo></mrow><mrow><mi>λ</mi><mi>n</mi></mrow></msup><msup><mrow><mo fence="true">(</mo><mi>n</mi><mo>+</mo><mi>λ</mi><mi>n</mi><mo>−</mo><mi>m</mi><mo>−</mo><mn>2</mn><mo fence="true">)</mo></mrow><mrow><mi>n</mi><mo>+</mo><mi>λ</mi><mi>n</mi><mo>−</mo><mi>m</mi><mo>−</mo><mn>2</mn></mrow></msup></mrow><mrow><msup><mrow><mo fence="true">(</mo><mi>λ</mi><mi>n</mi><mo>−</mo><mi>m</mi><mo fence="true">)</mo></mrow><mrow><mi>λ</mi><mi>n</mi><mo>−</mo><mi>m</mi></mrow></msup><msup><mrow><mo fence="true">(</mo><mi>n</mi><mo>+</mo><mi>λ</mi><mi>n</mi><mo>−</mo><mn>1</mn><mo fence="true">)</mo></mrow><mrow><mi>n</mi><mo>+</mo><mi>λ</mi><mi>n</mi><mo>−</mo><mn>1</mn></mrow></msup></mrow></mfrac><mi mathvariant="normal">e</mi></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow/></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow/><mo>=</mo><msup><mrow><mo fence="true">(</mo><mstyle displaystyle="false" scriptlevel="0"><mfrac><mrow><mi>n</mi><mo>+</mo><mi>λ</mi><mi>n</mi><mo>−</mo><mi>m</mi><mo>−</mo><mn>2</mn></mrow><mrow><mi>n</mi><mo>+</mo><mi>λ</mi><mi>n</mi><mo>−</mo><mn>1</mn></mrow></mfrac></mstyle><mo fence="true">)</mo></mrow><mi>n</mi></msup><msup><mrow><mo fence="true">(</mo><mstyle displaystyle="false" scriptlevel="0"><mfrac><mrow><mrow><mo fence="true">(</mo><mi>n</mi><mo>+</mo><mi>λ</mi><mi>n</mi><mo>−</mo><mi>m</mi><mo>−</mo><mn>2</mn><mo fence="true">)</mo></mrow><mi>λ</mi><mi>n</mi></mrow><mrow><mrow><mo fence="true">(</mo><mi>λ</mi><mi>n</mi><mo>−</mo><mi>m</mi><mo fence="true">)</mo></mrow><mrow><mo fence="true">(</mo><mi>n</mi><mo>+</mo><mi>λ</mi><mi>n</mi><mo>−</mo><mn>1</mn><mo fence="true">)</mo></mrow></mrow></mfrac></mstyle><mo fence="true">)</mo></mrow><mrow><mi>λ</mi><mi>n</mi></mrow></msup><msup><mrow><mo fence="true">(</mo><mstyle displaystyle="false" scriptlevel="0"><mfrac><mrow><mi>λ</mi><mi>n</mi><mo>−</mo><mi>m</mi></mrow><mrow><mi>n</mi><mo>+</mo><mi>λ</mi><mi>n</mi><mo>−</mo><mi>m</mi><mo>−</mo><mn>2</mn></mrow></mfrac></mstyle><mo fence="true">)</mo></mrow><mi>m</mi></msup><mstyle displaystyle="false" scriptlevel="0"><mfrac><mrow><mrow><mo fence="true">(</mo><mi>n</mi><mo>−</mo><mn>1</mn><mo fence="true">)</mo></mrow><mrow><mo fence="true">(</mo><mi>n</mi><mo>+</mo><mi>λ</mi><mi>n</mi><mo>−</mo><mn>1</mn><mo fence="true">)</mo></mrow></mrow><msup><mrow><mo fence="true">(</mo><mi>n</mi><mo>+</mo><mi>λ</mi><mi>n</mi><mo>−</mo><mi>m</mi><mo>−</mo><mn>2</mn><mo fence="true">)</mo></mrow><mn>2</mn></msup></mfrac></mstyle><mi mathvariant="normal">e</mi></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow/></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow/><mo>→</mo><msup><mi mathvariant="normal">e</mi><mrow><mo>−</mo><mfrac><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mrow><mi>λ</mi><mo>+</mo><mn>1</mn></mrow></mfrac></mrow></msup><mtext> </mtext><msup><mi mathvariant="normal">e</mi><mi>m</mi></msup><mtext> </mtext><msup><mi mathvariant="normal">e</mi><mrow><mo>−</mo><mfrac><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mrow><mi>λ</mi><mo>+</mo><mn>1</mn></mrow></mfrac><mi>λ</mi></mrow></msup><msup><mrow><mo fence="true">(</mo><mstyle displaystyle="false" scriptlevel="0"><mfrac><mi>λ</mi><mrow><mi>λ</mi><mo>+</mo><mn>1</mn></mrow></mfrac></mstyle><mo fence="true">)</mo></mrow><mi>m</mi></msup><mstyle displaystyle="false" scriptlevel="0"><mfrac><mn>1</mn><mrow><mi>λ</mi><mo>+</mo><mn>1</mn></mrow></mfrac></mstyle><mi mathvariant="normal">e</mi></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow/></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow/><mo>=</mo><msup><mrow><mo fence="true">(</mo><mstyle displaystyle="false" scriptlevel="0"><mfrac><mi>λ</mi><mrow><mi>λ</mi><mo>+</mo><mn>1</mn></mrow></mfrac></mstyle><mo fence="true">)</mo></mrow><mi>m</mi></msup><mstyle displaystyle="false" scriptlevel="0"><mfrac><mn>1</mn><mrow><mi>λ</mi><mo>+</mo><mn>1</mn></mrow></mfrac></mstyle><mi mathvariant="normal">.</mi></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">\begin{align*}
P_{n,k}(m)&amp;\sim\left(n-1\right)
\frac{\left(\lambda n\right)^{\lambda n}\left(n+\lambda n-m-2\right)^{n+\lambda n-m-2} }
{\left(\lambda n-m\right)^{\lambda n-m}\left(n+\lambda n-1\right)^{n+\lambda n-1}}\mathrm e\\
&amp;=\left(\tfrac{n+\lambda n-m-2}{n+\lambda n-1}\right)^n
\left(\tfrac{\left(n+\lambda n-m-2\right)\lambda n}{\left(\lambda n-m\right)\left(n+\lambda n-1\right)}\right)^{\lambda n}
\left(\tfrac{\lambda n-m}{n+\lambda n-m-2}\right)^m
\tfrac{\left(n-1\right)\left(n+\lambda n-1\right)}{\left(n+\lambda n-m-2\right)^2}\mathrm e\\
&amp;\to\mathrm e^{-\frac{m+1}{\lambda+1}}\,\mathrm e^m\,
\mathrm e^{-\frac{m+1}{\lambda+1}\lambda}\left(\tfrac\lambda{\lambda+1}\right)^m\tfrac1{\lambda+1}\mathrm e\\
&amp;=\left(\tfrac\lambda{\lambda+1}\right)^m\tfrac1{\lambda+1}.
\end{align*}</annotation></semantics></math></span></span></span>
This is just the geometric distribution with parameter <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi><mo>=</mo><mn>1</mn><mi mathvariant="normal">/</mi><mo stretchy="false">(</mo><mi>λ</mi><mo>+</mo><mn>1</mn><mo stretchy="false">)</mo><mo>=</mo><mi>n</mi><mi mathvariant="normal">/</mi><mo stretchy="false">(</mo><mi>k</mi><mo>+</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">p=1/(\lambda+1)=n/(k+n)</annotation></semantics></math></span></span>.</p>
<hr/>
<p>If you want to simulate the number of balls in a box, here is a simple way to do this. First, because each box is the same, we can just focus on the first box without loss of generality. Then, we just need to randomly generate the positions of the <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>−</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">n-1</annotation></semantics></math></span></span> bars among the <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>+</mo><mi>k</mi><mo>−</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">n+k-1</annotation></semantics></math></span></span> positions, and then return the index of the first bar (which is the number of balls in the first box).</p>
<p>We can then write the following Ruby code to simulate the number of balls in the first box:</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="k">def</span> <span class="nf">simulate</span> <span class="n">n</span><span class="p">,</span> <span class="n">k</span>
</span>
            <span class="line line-2">  <span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">).</span><span class="nf">times</span><span class="p">.</span><span class="nf">inject</span><span class="p">(</span><span class="n">npkm1</span> <span class="o">=</span> <span class="n">n</span><span class="o">+</span><span class="n">k</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span> <span class="o">|</span><span class="n">bar</span><span class="p">,</span> <span class="n">i</span><span class="o">|</span> <span class="p">[</span><span class="nb">rand</span><span class="p">(</span><span class="n">npkm1</span> <span class="o">-</span> <span class="n">i</span><span class="p">),</span> <span class="n">bar</span><span class="p">].</span><span class="nf">min</span> <span class="p">}</span>
</span>
            <span class="line line-3"><span class="k">end</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p>Compare the simulated result with the theoretical result:</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="k">def</span> <span class="nf">frequency</span> <span class="n">m</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">k</span><span class="p">,</span> <span class="n">trials</span>
</span>
            <span class="line line-2">  <span class="n">trials</span><span class="p">.</span><span class="nf">times</span><span class="p">.</span><span class="nf">count</span> <span class="p">{</span> <span class="n">simulate</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">k</span><span class="p">)</span> <span class="o">==</span> <span class="n">m</span> <span class="p">}</span> <span class="o">/</span> <span class="n">trials</span><span class="p">.</span><span class="nf">to_f</span>
</span>
            <span class="line line-3"><span class="k">end</span>
</span>
            <span class="line line-4">
</span>
            <span class="line line-5"><span class="k">def</span> <span class="nf">truth</span> <span class="n">m</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">k</span>
</span>
            <span class="line line-6">  <span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">k</span><span class="o">-</span><span class="n">m</span><span class="o">+</span><span class="mi">1</span><span class="o">..</span><span class="n">k</span><span class="p">).</span><span class="nf">reduce</span><span class="p">(</span><span class="mi">1</span><span class="p">,:</span><span class="o">*</span><span class="p">)</span> <span class="o">/</span> <span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="n">k</span><span class="o">-</span><span class="n">m</span><span class="o">-</span><span class="mi">1</span><span class="o">..</span><span class="n">n</span><span class="o">+</span><span class="n">k</span><span class="o">-</span><span class="mi">1</span><span class="p">).</span><span class="nf">reduce</span><span class="p">(</span><span class="mi">1</span><span class="p">,:</span><span class="o">*</span><span class="p">).</span><span class="nf">to_f</span>
</span>
            <span class="line line-7"><span class="k">end</span>
</span>
            <span class="line line-8">
</span>
            <span class="line line-9"><span class="k">def</span> <span class="nf">approx</span> <span class="n">m</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">k</span>
</span>
            <span class="line line-10">  <span class="n">n</span><span class="o">*</span><span class="n">k</span><span class="o">**</span><span class="n">m</span> <span class="o">/</span> <span class="p">((</span><span class="n">n</span><span class="o">+</span><span class="n">k</span><span class="p">)</span><span class="o">**</span><span class="p">(</span><span class="n">m</span><span class="o">+</span><span class="mi">1</span><span class="p">)).</span><span class="nf">to_f</span>
</span>
            <span class="line line-11"><span class="k">end</span>
</span>
            <span class="line line-12">
</span>
            <span class="line line-13"><span class="nb">srand</span> <span class="mi">1108</span>
</span>
            <span class="line line-14"><span class="n">m</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5000</span><span class="p">,</span> <span class="mi">8000</span>
</span>
            <span class="line line-15"><span class="nb">p</span> <span class="n">frequency</span> <span class="n">m</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">k</span><span class="p">,</span> <span class="mi">10000</span> <span class="c1"># =&gt; 0.0902</span>
</span>
            <span class="line line-16"><span class="nb">p</span> <span class="n">truth</span> <span class="n">m</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">k</span> <span class="c1"># =&gt; 0.08965012972626446</span>
</span>
            <span class="line line-17"><span class="nb">p</span> <span class="n">approx</span> <span class="n">m</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">k</span> <span class="c1"># =&gt; 0.08963271594131858</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>]]></content><author><name>UlyssesZhan</name><email>ulysseszhan@gmail.com</email></author><category term="math" /><category term="probability" /><category term="combinatorics" /><category term="ruby" /><summary type="html"><![CDATA[Suppose there are <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span></span> distinguishable boxes and <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi></mrow><annotation encoding="application/x-tex">k</annotation></semantics></math></span></span> indistinguishable balls. Now, we randomly put the balls into the boxes. For each of the boxes, what is the probability that it contains <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span></span> balls? This is a simple combanitorics problem that can be solved by the stars and bars method. It turns out that in the limit <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo separator="true">,</mo><mi>k</mi><mo>→</mo><mi mathvariant="normal">∞</mi></mrow><annotation encoding="application/x-tex">n,k\to\infty</annotation></semantics></math></span></span> with <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi><mi mathvariant="normal">/</mi><mi>n</mi></mrow><annotation encoding="application/x-tex">k/n</annotation></semantics></math></span></span> fixed, the distribution tends to be a geometric distribution.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://ulysseszh.github.io/assets/images/covers/2023-05-09-stars-bars-geometric.png" /><media:content medium="image" url="https://ulysseszh.github.io/assets/images/covers/2023-05-09-stars-bars-geometric.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html"><![CDATA[Labeled <code>break</code>, <code>next</code>, and <code>redo</code> in Ruby]]></title><link href="https://ulysseszh.github.io/programming/2023/05/07/ruby-jump-label.html" rel="alternate" type="text/html" title="Labeled break, next, and redo in Ruby" /><published>2023-05-07T13:36:16-07:00</published><updated>2023-05-07T13:36:16-07:00</updated><id>https://ulysseszh.github.io/programming/2023/05/07/ruby-jump-label</id><content type="html" xml:base="https://ulysseszh.github.io/programming/2023/05/07/ruby-jump-label.html"><![CDATA[<p>Many languages support breaking out of nested loops. There are some typical ways of doing this:</p>
<ul>
<li>Some languages can name loops by providing a label for the loop. In those languages, you can use <code>break</code> together with a label to specify which loop to break out of. Examples: Perl, Java, JavaScript, and some others.</li>
<li>Some languages can specify the number of layers of loops to break out of. In those languages, you can use <code>break</code> together with a number to specify how many layers of loops to break out of. The only example that I know is C#.</li>
<li>Some languages have <code>goto</code> statements. You can easily break from loops to wherever you want by using <code>goto</code> (actually breaking out of nested loops is among the only recommended cases for using <code>goto</code>). Examples: C, C++.</li>
</ul>
<p>However, in most other languages, it is not easy to break out of nested loops. A typical solution is this:</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="n">outer_loop</span> <span class="k">do</span>
</span>
            <span class="line line-2">	<span class="n">break_outer</span> <span class="o">=</span> <span class="kp">false</span>
</span>
            <span class="line line-3">	<span class="n">inner_loop</span> <span class="k">do</span>
</span>
            <span class="line line-4">		<span class="k">if</span> <span class="n">condition</span>
</span>
            <span class="line line-5">			<span class="n">break_outer</span> <span class="o">=</span> <span class="kp">true</span>
</span>
            <span class="line line-6">			<span class="k">break</span>
</span>
            <span class="line line-7">		<span class="k">end</span>
</span>
            <span class="line line-8">	<span class="k">end</span>
</span>
            <span class="line line-9">	<span class="k">break</span> <span class="k">if</span> <span class="n">break_outer</span>
</span>
            <span class="line line-10"><span class="k">end</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p>In languages with exceptions, another possible workaround is to use exceptions (the catch–throw control flow):</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="kp">catch</span> <span class="ss">:outer_loop</span> <span class="k">do</span>
</span>
            <span class="line line-2">	<span class="n">outer_loop</span> <span class="k">do</span>
</span>
            <span class="line line-3">		<span class="n">inner_loop</span> <span class="k">do</span>
</span>
            <span class="line line-4">			<span class="kp">throw</span> <span class="ss">:outer_loop</span> <span class="k">if</span> <span class="n">condition</span>
</span>
            <span class="line line-5">		<span class="k">end</span>
</span>
            <span class="line line-6">	<span class="k">end</span>
</span>
            <span class="line line-7"><span class="k">end</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p>I wrote a simple module to better use this workaround.</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="k">class</span> <span class="nc">JumpLabel</span> <span class="o">&lt;</span> <span class="no">StandardError</span>
</span>
            <span class="line line-2">	<span class="nb">attr_reader</span> <span class="ss">:reason</span><span class="p">,</span> <span class="ss">:arg</span>
</span>
            <span class="line line-3">	<span class="p">{</span><span class="ss">break: </span><span class="kp">true</span><span class="p">,</span> <span class="ss">next: </span><span class="kp">true</span><span class="p">,</span> <span class="ss">redo: </span><span class="kp">false</span><span class="p">}.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">reason</span><span class="p">,</span> <span class="n">has_args</span><span class="o">|</span>
</span>
            <span class="line line-4">		<span class="n">define_method</span> <span class="n">reason</span> <span class="k">do</span> <span class="o">|*</span><span class="n">args</span><span class="o">|</span>
</span>
            <span class="line line-5">			<span class="vi">@reason</span> <span class="o">=</span> <span class="n">reason</span>
</span>
            <span class="line line-6">			<span class="vi">@arg</span> <span class="o">=</span> <span class="n">args</span><span class="p">.</span><span class="nf">size</span> <span class="o">==</span> <span class="mi">1</span> <span class="p">?</span> <span class="n">args</span><span class="p">.</span><span class="nf">first</span> <span class="p">:</span> <span class="n">args</span> <span class="k">if</span> <span class="n">has_args</span>
</span>
            <span class="line line-7">			<span class="k">raise</span> <span class="nb">self</span>
</span>
            <span class="line line-8">		<span class="k">end</span>
</span>
            <span class="line line-9">	<span class="k">end</span>
</span>
            <span class="line line-10"><span class="k">end</span>
</span>
            <span class="line line-11">
</span>
            <span class="line line-12"><span class="k">class</span> <span class="nc">Module</span>
</span>
            <span class="line line-13">	<span class="k">def</span> <span class="nf">register_label</span> <span class="o">*</span><span class="n">method_names</span>
</span>
            <span class="line line-14">		<span class="n">method_names</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="nb">name</span><span class="o">|</span>
</span>
            <span class="line line-15">			<span class="n">old</span> <span class="o">=</span> <span class="nb">instance_method</span> <span class="nb">name</span>
</span>
            <span class="line line-16">			<span class="n">define_method</span> <span class="nb">name</span> <span class="k">do</span> <span class="o">|*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span><span class="o">|</span>
</span>
            <span class="line line-17">				<span class="k">return</span> <span class="n">old</span><span class="p">.</span><span class="nf">bind_call</span> <span class="nb">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span> <span class="k">unless</span> <span class="n">block</span>
</span>
            <span class="line line-18">				<span class="n">old</span><span class="p">.</span><span class="nf">bind_call</span> <span class="nb">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span> <span class="k">do</span> <span class="o">|*</span><span class="n">bargs</span><span class="p">,</span> <span class="o">**</span><span class="n">bopts</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">bblock</span><span class="o">|</span>
</span>
            <span class="line line-19">					<span class="n">block</span><span class="p">.</span><span class="nf">call</span> <span class="o">*</span><span class="n">bargs</span><span class="p">,</span> <span class="o">**</span><span class="n">bopts</span><span class="p">,</span> <span class="ss">jump_label: </span><span class="n">label</span> <span class="o">=</span> <span class="no">JumpLabel</span><span class="p">.</span><span class="nf">new</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">bblock</span>
</span>
            <span class="line line-20">				<span class="k">rescue</span> <span class="no">JumpLabel</span> <span class="o">=&gt;</span> <span class="n">catched_label</span>
</span>
            <span class="line line-21">					<span class="k">raise</span> <span class="n">catched_label</span> <span class="k">unless</span> <span class="n">catched_label</span> <span class="o">==</span> <span class="n">label</span>
</span>
            <span class="line line-22">					<span class="k">case</span> <span class="n">label</span><span class="p">.</span><span class="nf">reason</span>
</span>
            <span class="line line-23">					<span class="k">when</span> <span class="ss">:break</span> <span class="k">then</span> <span class="k">break</span> <span class="n">label</span><span class="p">.</span><span class="nf">arg</span>
</span>
            <span class="line line-24">					<span class="k">when</span> <span class="ss">:next</span> <span class="k">then</span> <span class="k">next</span> <span class="n">label</span><span class="p">.</span><span class="nf">arg</span>
</span>
            <span class="line line-25">					<span class="k">when</span> <span class="ss">:redo</span> <span class="k">then</span> <span class="k">redo</span>
</span>
            <span class="line line-26">					<span class="k">end</span>
</span>
            <span class="line line-27">				<span class="k">end</span>
</span>
            <span class="line line-28">			<span class="k">end</span>
</span>
            <span class="line line-29">		<span class="k">end</span>
</span>
            <span class="line line-30">	<span class="k">end</span>
</span>
            <span class="line line-31"><span class="k">end</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p>Example usage:</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="no">Integer</span><span class="p">.</span><span class="nf">register_label</span> <span class="ss">:upto</span><span class="p">,</span> <span class="ss">:downto</span>
</span>
            <span class="line line-2"><span class="mi">1</span><span class="p">.</span><span class="nf">upto</span> <span class="mi">520</span> <span class="k">do</span> <span class="o">|</span><span class="n">i</span><span class="p">,</span> <span class="n">jump_label</span><span class="ss">:|</span>
</span>
            <span class="line line-3">	<span class="nb">print</span> <span class="n">i</span>
</span>
            <span class="line line-4">	<span class="mi">1</span><span class="p">.</span><span class="nf">downto</span> <span class="o">-</span><span class="mi">1314</span> <span class="k">do</span> <span class="o">|</span><span class="n">j</span><span class="o">|</span>
</span>
            <span class="line line-5">		<span class="nb">print</span> <span class="n">j</span>
</span>
            <span class="line line-6">		<span class="n">jump_label</span><span class="p">.</span><span class="nf">break</span> <span class="mi">8</span> <span class="k">if</span> <span class="n">j</span> <span class="o">==</span> <span class="mi">0</span>
</span>
            <span class="line line-7">	<span class="k">end</span>
</span>
            <span class="line line-8"><span class="k">end</span><span class="p">.</span><span class="nf">tap</span> <span class="p">{</span> <span class="nb">puts</span> <span class="n">_1</span> <span class="p">}</span>
</span>
            <span class="line line-9"><span class="c1"># =&gt; 1108</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>]]></content><author><name>UlyssesZhan</name><email>ulysseszhan@gmail.com</email></author><category term="programming" /><category term="meta programming" /><category term="ruby" /><summary type="html"><![CDATA[Many languages support breaking out of nested loops, such as Perl, Java, JavaScript, C#, etc. Languages that have <code>goto</code> can also do this easily. However, in most other languages, it is not easy to break out of nested loops. I want to introduce a way to do this in Ruby.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://ulysseszh.github.io/assets/images/covers/2023-05-07-ruby-jump-label.png" /><media:content medium="image" url="https://ulysseszh.github.io/assets/images/covers/2023-05-07-ruby-jump-label.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html"><![CDATA[I made this, for the number of days in a week is prime]]></title><link href="https://ulysseszh.github.io/programming/2022/12/05/week-prime.html" rel="alternate" type="text/html" title="I made this, for the number of days in a week is prime" /><published>2022-12-05T10:23:34-08:00</published><updated>2022-12-05T10:23:34-08:00</updated><id>https://ulysseszh.github.io/programming/2022/12/05/week-prime</id><content type="html" xml:base="https://ulysseszh.github.io/programming/2022/12/05/week-prime.html"><![CDATA[<p>The number of days in a week is prime, so we cannot utilize weekly periods to help us remember periodical events unless the period is a multiple of 7. However, there may be something that we need to get reminded of which happens once per two days or three days. For example, I wash my hair once per two days and wash my clothes once per eight days.</p>
<p>I may use calendar apps to help me with that, but there is a problem around it: most calendar apps set periodical events based on weeks (i.e. you can set an event to happen on every Monday but can not set it to happen every other day). Since my need is actually very easy to satisfy (I just need a reliable reminder!), I decided to write a Ruby program to help me with that.</p>
<p>The program is called peroutine. It is available <a href="https://github.com/UlyssesZh/peroutine" target="_blank" rel="external">on GitHub</a>. It is a Ruby program that runs on the command line. I can now see whether I need to wash my hair or clothes today by running <code>peroutine list</code>! It also notifies me every day at 11 PM via my self-hosted <a href="https://ntfy.sh" target="_blank" rel="external">ntfy</a> server whether I need to wash my hair today.</p>]]></content><author><name>UlyssesZhan</name><email>ulysseszhan@gmail.com</email></author><category term="programming" /><category term="selfhosting" /><category term="linux" /><category term="ruby" /><summary type="html"><![CDATA[The number of days in a week is prime, so we cannot utilize weekly periods to help us remember periodical events unless the period is a multiple of 7. However, there may be something that we need to get reminded of which happens once per two days or three days. For example, I wash my hair once per two days and wash my clothes once per eight days. To solve the problem, I wrote a Ruby program to help remind me of those routines.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://ulysseszh.github.io/assets/images/covers/2022-12-05-week-prime.png" /><media:content medium="image" url="https://ulysseszh.github.io/assets/images/covers/2022-12-05-week-prime.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html"><![CDATA[Typesetting math in emails]]></title><link href="https://ulysseszh.github.io/programming/2022/11/08/math-emails.html" rel="alternate" type="text/html" title="Typesetting math in emails" /><published>2022-11-08T11:12:09-08:00</published><updated>2022-11-08T11:12:09-08:00</updated><id>https://ulysseszh.github.io/programming/2022/11/08/math-emails</id><content type="html" xml:base="https://ulysseszh.github.io/programming/2022/11/08/math-emails.html"><![CDATA[<p>After I become a university student, I start to heavily rely on emails to communicate with professors or teaching assistants. However, there is a problem around this form of communication considering that I am physics major: I cannot typeset math in emails.</p>
<p>Emails normally have two types of message body: plain text and HTML. Plain text is just plain text, we do not expect it to have any typesetting ability itself. However, HTML is a much more capable content type.</p>
<p>In theory, we should be able to ask the HTML renderer to typeset math by using <a href="https://developer.mozilla.org/en-US/docs/Web/MathML/Element/math" target="_blank" rel="external"><code>&lt;math&gt;</code> elements</a> (MathML). However, modern browsers generally do not support them by default. As for today (when this post is created), the only modern browsers that support MathML without modifications are Firefox and Safari. Chrome, Edge, and Opera support MathML only when the <code>#enable-experimental-web-platform-features</code> preferences are set to <code>Enabled</code>. Supporting for MathML is even worse if we are considering mobile browsers or email clients. Therefore, MathML should not be our first choice although it could have been the most elegant way.</p>
<p>The next choice is to use <code>&lt;img&gt;</code> or <code>&lt;svg&gt;</code> elements. There are two ways of doing this: host a server that has API to convert math to images; or, write a program to generate the email with all images generated (as image data URLs or <code>&lt;svg&gt;</code> elements) as well (actually I have already found a solution for such programs: <a href="https://rubygems.org/gems/mathematical" target="_blank" rel="external">mathematical</a>). The first way have the following disadvantages:</p>
<ul>
<li>It requires me to either use some third-party service (like <a href="https://latex.codecogs.com" target="_blank" rel="external">CODECOGS Equation Renderer</a>) or maintain a public server which would be exposed to my email receivers.</li>
<li>It is hard for me make the position of the baseline of rendered math correctly.</li>
<li>Email clients will probably block images from remote sources.</li>
</ul>
<p class="no-indent">
Both ways have the following disadvantages:
</p>
<ul>
<li>There is no “half-working”—either the math is rendered, or it cannot be read at all (on email clients that do not support or block <code>&lt;img&gt;</code> or <code>&lt;svg&gt;</code> elements).</li>
<li>Math expressions cannot have line breaks in the middle.</li>
<li>Images normally have a larger bandwidth burden.</li>
<li>It is hard to get them aware of the context (text size, color, etc.).</li>
</ul>
<p class="no-indent">
Therefore, I try to seek other ways.
</p>
<p>You may wonder how I typeset math in my blog. The answer is that I use <a href="https://mathjax.org" target="_blank" rel="external">MathJax</a>. To integrate it on a webpage, I just load a JavaScript script to the webpage, and it will convert all the <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mtext>TeX</mtext></mrow><annotation encoding="application/x-tex">\TeX</annotation></semantics></math></span></span> expressions to math. Although we normally cannot have JavaScript in emails, this is actually also a good candidate for typesetting math in emails because I can <a href="https://docs.mathjax.org/en/latest/server/start.html" target="_blank" rel="external">use its Node.js module</a> to generate the email with math typeset. The generated email already has all the math rendered, and there is no client-side JavaScript needed.</p>
<p>However, before using Node.js to write my program of generating email, I looked into <a href="https://katex.org" target="_blank" rel="external">KaTeX</a>. How KaTeX advertise itself is saying that it is the <em>fastest</em> math typesetting library for the web. Well, actually I do not care about the speed of typesetting, but there is something about KaTeX that I found interesting: <a href="https://rubygems.org/gems/kramdown-math-katex" target="_blank" rel="external">kramdown-math-katex</a>, which implements for us the conversion from Markdown to HTML with math typeset. I am familiar with Ruby and prefer a Ruby project to a Node.js project, so this looks amazing to me. What is more amazing is that I can combine it with <a href="https://jekyllrb.com" target="_blank" rel="external">Jekyll</a> to create even more possibility about how I can generate my email.</p>
<p>Then, I implemented my idea and finally created <a href="https://github.com/UlyssesZh/genmail" target="_blank" rel="external">this</a>. I have already used it to generate some emails (such as <a href="/physics/2022/11/07/map-kepler-3-sphere.html">this one</a>). I then just paste the generated HTML into the HTML editor of my email client (Thunderbird, with <a href="https://betterbird.eu/addons/#ThunderHTMLedit" target="_blank" rel="external">this add-on</a>).</p>
<p>By generating the email, the email receivers can see the math typeset without running any JavaScript on their clients. However, they need their email client to support CSS styling (Thunderbird does). I need to inform the receiver of this every time I send an email containing math.</p>]]></content><author><name>UlyssesZhan</name><email>ulysseszhan@gmail.com</email></author><category term="programming" /><category term="jekyll" /><category term="ruby" /><category term="tex" /><summary type="html"><![CDATA[After some comparison among solutions, I use KaTeX to typeset math in my emails.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://ulysseszh.github.io/assets/images/covers/2022-11-08-math-emails.png" /><media:content medium="image" url="https://ulysseszh.github.io/assets/images/covers/2022-11-08-math-emails.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html"><![CDATA[Simulating a mechanical system using RGSS3]]></title><link href="https://ulysseszh.github.io/physics/2020/04/28/simulation-rgss.html" rel="alternate" type="text/html" title="Simulating a mechanical system using RGSS3" /><published>2020-04-27T20:51:17-07:00</published><updated>2020-04-27T20:51:17-07:00</updated><id>https://ulysseszh.github.io/physics/2020/04/28/simulation-rgss</id><content type="html" xml:base="https://ulysseszh.github.io/physics/2020/04/28/simulation-rgss.html"><![CDATA[<p>Our goal is to simulate a mechanical system according to its Hamiltonian <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="script">H</mi><mtext> ⁣</mtext><mrow><mo fence="true">(</mo><mi mathvariant="bold">q</mi><mo separator="true">,</mo><mi mathvariant="bold">p</mi><mo separator="true">,</mo><mi>t</mi><mo fence="true">)</mo></mrow></mrow><annotation encoding="application/x-tex">\mathcal H\!\left(\mathbf q,\mathbf p,t\right)</annotation></semantics></math></span></span>.</p>
<p>To utilize the canonical equations <span id="eq:canonical" data-label="(1)"><span class="katex-display-table"> <span class="katex-display-numbered"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mfrac><mrow><mi mathvariant="normal">d</mi><mi mathvariant="bold">q</mi></mrow><mrow><mi mathvariant="normal">d</mi><mi>t</mi></mrow></mfrac><mo>=</mo><mfrac><mrow><mi mathvariant="normal">∂</mi><mi mathvariant="script">H</mi></mrow><mrow><mi mathvariant="normal">∂</mi><mi mathvariant="bold">p</mi></mrow></mfrac><mo separator="true">,</mo><mspace width="1em"/><mfrac><mrow><mi mathvariant="normal">d</mi><mi mathvariant="bold">p</mi></mrow><mrow><mi mathvariant="normal">d</mi><mi>t</mi></mrow></mfrac><mo>=</mo><mo>−</mo><mfrac><mrow><mi mathvariant="normal">∂</mi><mi mathvariant="script">H</mi></mrow><mrow><mi mathvariant="normal">∂</mi><mi mathvariant="bold">p</mi></mrow></mfrac><mo separator="true">,</mo></mrow><annotation encoding="application/x-tex">\frac{\mathrm d\mathbf q}{\mathrm dt}=
    \frac{\partial\mathcal H}{\partial\mathbf p},\quad
    \frac{\mathrm d\mathbf p}{\mathrm dt}=
    -\frac{\partial\mathcal H}{\partial\mathbf p},</annotation></semantics></math></span></span></span></span> <span class="katex-display-number"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(1)</annotation></semantics></math></span></span></span></span> </span></span> we need to calculate the partial derivatives of <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="script">H</mi></mrow><annotation encoding="application/x-tex">\mathcal H</annotation></semantics></math></span></span>. Here is a simple code to calculate partial derivatives.</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="k">def</span> <span class="nf">div</span> <span class="n">x0</span><span class="p">,</span> <span class="n">dx</span><span class="p">,</span> <span class="n">f</span>
</span>
            <span class="line line-2">	<span class="n">f0</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="p">(</span><span class="n">x0</span><span class="p">)</span>
</span>
            <span class="line line-3">	<span class="n">n</span> <span class="o">=</span> <span class="n">x0</span><span class="p">.</span><span class="nf">size</span>
</span>
            <span class="line line-4">	<span class="no">Array</span><span class="p">.</span><span class="nf">new</span> <span class="n">n</span> <span class="k">do</span> <span class="o">|</span><span class="n">i</span><span class="o">|</span>
</span>
            <span class="line line-5">		<span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="p">(</span><span class="n">x0</span> <span class="o">+</span> <span class="no">Vector</span><span class="p">.</span><span class="nf">basis</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span> <span class="o">*</span> <span class="n">dx</span><span class="p">)</span> <span class="o">-</span> <span class="n">f0</span><span class="p">)</span> <span class="o">/</span> <span class="n">dx</span>
</span>
            <span class="line line-6">	<span class="k">end</span>
</span>
            <span class="line line-7"><span class="k">end</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p class="no-indent">
(RGSS do not have <code>matrix.rb</code>, you can copy one from the attached file below.) Here <code>x0</code> is a <code>Vector</code>, <code>f</code> is a <code>call</code>-able object as a function of vectors, <code>dx</code> is a small scalar which we are going to take <code>1e-6</code>.
</p>
<p>Let <code>x = Vector[*q, *p]</code>, and then Formula <a href="#eq:canonical">1</a> has the form <span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mfrac><mrow><mi mathvariant="normal">d</mi><mi mathvariant="bold">x</mi></mrow><mrow><mi mathvariant="normal">d</mi><mi>t</mi></mrow></mfrac><mo>=</mo><mi>f</mi><mtext> ⁣</mtext><mrow><mo fence="true">(</mo><mi mathvariant="bold">x</mi><mo fence="true">)</mo></mrow><mi mathvariant="normal">.</mi></mrow><annotation encoding="application/x-tex">\frac{\mathrm d\mathbf x}{\mathrm dt}=f\!\left(\mathbf x\right).</annotation></semantics></math></span></span></span> To solve this equation numerically, we need to use a famous method called the (explicit) Runge–Kutta method.</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="k">def</span> <span class="nf">runge_kutta</span> <span class="n">initial</span><span class="p">,</span> <span class="n">max_t</span><span class="p">,</span> <span class="n">dt</span><span class="p">,</span> <span class="p">(</span><span class="o">*</span><span class="n">pyramid</span><span class="p">,</span> <span class="n">coefs</span><span class="p">),</span> <span class="n">func</span>
</span>
            <span class="line line-2">	<span class="p">(</span><span class="mi">0</span><span class="o">..</span><span class="n">max_t</span><span class="p">).</span><span class="nf">step</span><span class="p">(</span><span class="n">dt</span><span class="p">).</span><span class="nf">reduce</span> <span class="n">initial</span> <span class="k">do</span> <span class="o">|</span><span class="n">ret</span><span class="p">,</span> <span class="n">t</span><span class="o">|</span>
</span>
            <span class="line line-3">		<span class="vg">$canvas</span><span class="p">.</span><span class="nf">trace</span> <span class="n">t</span><span class="p">,</span> <span class="n">ret</span> <span class="k">if</span> <span class="vg">$canvas</span>
</span>
            <span class="line line-4">		<span class="n">coefs</span><span class="p">.</span><span class="nf">zip</span><span class="p">(</span><span class="n">pyramid</span><span class="p">).</span><span class="nf">each_with_object</span><span class="p">([]).</span><span class="nf">sum</span> <span class="k">do</span> <span class="o">|</span><span class="p">(</span><span class="n">coef</span><span class="p">,</span> <span class="n">row</span><span class="p">),</span> <span class="n">ary</span><span class="o">|</span>
</span>
            <span class="line line-5">			<span class="n">coef</span> <span class="o">*</span> <span class="n">ary</span><span class="p">.</span><span class="nf">push</span><span class="p">(</span><span class="n">func</span><span class="o">.</span><span class="p">(</span><span class="n">t</span><span class="p">,</span> <span class="n">row</span><span class="p">.</span><span class="nf">inner</span><span class="p">(</span><span class="n">ary</span><span class="p">)</span> <span class="o">*</span> <span class="n">dt</span> <span class="o">+</span> <span class="n">ret</span><span class="p">)).</span><span class="nf">last</span>
</span>
            <span class="line line-6">		<span class="k">end</span> <span class="o">*</span> <span class="n">dt</span> <span class="o">+</span> <span class="n">ret</span><span class="c1">#p(ret)</span>
</span>
            <span class="line line-7">	<span class="k">end</span>
</span>
            <span class="line line-8"><span class="k">end</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p class="no-indent">
Note that Runge–Kutta is a family of methods. The argument <code>(*pyramid, coefs)</code> takes one of the following, each of which is a single Runge–Kutta method.
</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="no">FORWARD_EULER</span> <span class="o">=</span> <span class="p">[[],[</span><span class="mi">1</span><span class="p">]]</span>
</span>
            <span class="line line-2"><span class="no">EXPLICIT_MIDPOINT</span> <span class="o">=</span> <span class="p">[[],[</span><span class="mi">1</span><span class="o">/</span><span class="mf">2.0</span><span class="p">],[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]]</span>
</span>
            <span class="line line-3"><span class="no">HEUN</span> <span class="o">=</span> <span class="p">[[],[</span><span class="mi">1</span><span class="p">],[</span><span class="mi">1</span><span class="o">/</span><span class="mf">2.0</span><span class="p">,</span><span class="mi">1</span><span class="o">/</span><span class="mf">2.0</span><span class="p">]]</span>
</span>
            <span class="line line-4"><span class="no">RALSTON</span> <span class="o">=</span> <span class="p">[[],[</span><span class="mi">2</span><span class="o">/</span><span class="mf">3.0</span><span class="p">],[</span><span class="mi">1</span><span class="o">/</span><span class="mf">4.0</span><span class="p">,</span><span class="mi">3</span><span class="o">/</span><span class="mf">4.0</span><span class="p">]]</span>
</span>
            <span class="line line-5"><span class="no">KUTTA_3RD</span> <span class="o">=</span> <span class="p">[[],[</span><span class="mi">1</span><span class="o">/</span><span class="mf">2.0</span><span class="p">],[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],[</span><span class="mi">1</span><span class="o">/</span><span class="mf">6.0</span><span class="p">,</span><span class="mi">2</span><span class="o">/</span><span class="mf">3.0</span><span class="p">,</span><span class="mi">1</span><span class="o">/</span><span class="mf">6.0</span><span class="p">]]</span>
</span>
            <span class="line line-6"><span class="no">HEUN_3RD</span> <span class="o">=</span> <span class="p">[[],[</span><span class="mi">1</span><span class="o">/</span><span class="mf">3.0</span><span class="p">],[</span><span class="mi">0</span><span class="p">,</span><span class="mi">2</span><span class="o">/</span><span class="mf">3.0</span><span class="p">],[</span><span class="mi">1</span><span class="o">/</span><span class="mf">4.0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="o">/</span><span class="mf">4.0</span><span class="p">]]</span>
</span>
            <span class="line line-7"><span class="no">RALSTON_3RD</span> <span class="o">=</span> <span class="p">[[],[</span><span class="mi">1</span><span class="o">/</span><span class="mf">2.0</span><span class="p">],[</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="o">/</span><span class="mf">4.0</span><span class="p">],[</span><span class="mi">2</span><span class="o">/</span><span class="mf">9.0</span><span class="p">,</span><span class="mi">1</span><span class="o">/</span><span class="mf">3.0</span><span class="p">,</span><span class="mi">4</span><span class="o">/</span><span class="mf">9.0</span><span class="p">]]</span>
</span>
            <span class="line line-8"><span class="no">SSPRK3</span> <span class="o">=</span> <span class="p">[[],[</span><span class="mi">1</span><span class="p">],[</span><span class="mi">1</span><span class="o">/</span><span class="mf">4.0</span><span class="p">,</span><span class="mi">1</span><span class="o">/</span><span class="mf">4.0</span><span class="p">],[</span><span class="mi">1</span><span class="o">/</span><span class="mf">6.0</span><span class="p">,</span><span class="mi">1</span><span class="o">/</span><span class="mf">6.0</span><span class="p">,</span><span class="mi">2</span><span class="o">/</span><span class="mf">3.0</span><span class="p">]]</span>
</span>
            <span class="line line-9"><span class="no">CLASSIC_4TH</span> <span class="o">=</span> <span class="p">[[],[</span><span class="mi">1</span><span class="o">/</span><span class="mf">2.0</span><span class="p">],[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="o">/</span><span class="mf">2.0</span><span class="p">],[</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">],[</span><span class="mi">1</span><span class="o">/</span><span class="mf">6.0</span><span class="p">,</span><span class="mi">1</span><span class="o">/</span><span class="mf">3.0</span><span class="p">,</span><span class="mi">1</span><span class="o">/</span><span class="mf">3.0</span><span class="p">,</span><span class="mi">1</span><span class="o">/</span><span class="mf">6.0</span><span class="p">]]</span>
</span>
            <span class="line line-10"><span class="no">RALSTON_4TH</span> <span class="o">=</span> <span class="p">[[],[</span><span class="mf">0.4</span><span class="p">],[</span><span class="mf">0.29697761</span><span class="p">,</span><span class="mf">0.15875964</span><span class="p">],[</span><span class="mf">0.21810040</span><span class="p">,</span><span class="o">-</span><span class="mf">3.05096516</span><span class="p">,</span>
</span>
            <span class="line line-11">		<span class="mf">3.83286476</span><span class="p">],[</span><span class="mf">0.17476028</span><span class="p">,</span> <span class="o">-</span><span class="mf">0.55148066</span><span class="p">,</span> <span class="mf">1.20553560</span><span class="p">,</span> <span class="mf">0.17118478</span><span class="p">]]</span>
</span>
            <span class="line line-12"><span class="no">THREE_EIGHTH_4TH</span> <span class="o">=</span> <span class="p">[[],[</span><span class="mi">1</span><span class="o">/</span><span class="mf">3.0</span><span class="p">],[</span><span class="o">-</span><span class="mi">1</span><span class="o">/</span><span class="mf">3.0</span><span class="p">,</span><span class="mi">1</span><span class="p">],[</span><span class="mi">1</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">],[</span><span class="mi">1</span><span class="o">/</span><span class="mf">8.0</span><span class="p">,</span><span class="mi">3</span><span class="o">/</span><span class="mf">8.0</span><span class="p">,</span><span class="mi">3</span><span class="o">/</span><span class="mf">8.0</span><span class="p">,</span><span class="mi">1</span><span class="o">/</span><span class="mf">8.0</span><span class="p">]]</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p>Here we are going to take <code>CLASSIC_4TH</code>.</p>
<p>The <code>$canvas</code> appearing here is an object that is going to draw the result onto the screen.</p>
<p>Here we also need to have some patches to get it work.</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="k">class</span> <span class="nc">Float</span>
</span>
            <span class="line line-2">	<span class="k">alias</span> <span class="n">ulysses20200426121236_add</span> <span class="o">+</span>
</span>
            <span class="line line-3">	<span class="k">def</span> <span class="nf">+</span> <span class="n">other</span>
</span>
            <span class="line line-4">		<span class="k">if</span> <span class="n">zero?</span> <span class="o">&amp;&amp;</span> <span class="p">[</span><span class="no">Vector</span><span class="p">,</span> <span class="no">Matrix</span><span class="p">].</span><span class="nf">any?</span> <span class="p">{</span> <span class="o">|</span><span class="n">c</span><span class="o">|</span> <span class="n">other</span><span class="p">.</span><span class="nf">is_a?</span> <span class="n">c</span> <span class="p">}</span>
</span>
            <span class="line line-5">			<span class="n">other</span>
</span>
            <span class="line line-6">		<span class="k">else</span>
</span>
            <span class="line line-7">			<span class="n">ulysses20200426121236_add</span> <span class="n">other</span>
</span>
            <span class="line line-8">		<span class="k">end</span>
</span>
            <span class="line line-9">	<span class="k">end</span>
</span>
            <span class="line line-10"><span class="k">end</span>
</span>
            <span class="line line-11"><span class="k">module</span> <span class="nn">Enumerable</span>
</span>
            <span class="line line-12">	<span class="k">def</span> <span class="nf">sum</span> <span class="n">init</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span>
</span>
            <span class="line line-13">		<span class="p">(</span><span class="n">block</span> <span class="p">?</span> <span class="n">map</span><span class="p">(</span><span class="o">&amp;</span><span class="n">block</span><span class="p">)</span> <span class="p">:</span> <span class="nb">self</span><span class="p">).</span><span class="nf">reduce</span> <span class="n">init</span><span class="p">,</span> <span class="p">:</span><span class="o">+</span>
</span>
            <span class="line line-14">	<span class="k">end</span>
</span>
            <span class="line line-15"><span class="k">end</span>
</span>
            <span class="line line-16"><span class="k">class</span> <span class="nc">Array</span>
</span>
            <span class="line line-17">	<span class="k">def</span> <span class="nf">inner</span> <span class="n">other</span>
</span>
            <span class="line line-18">		<span class="n">zip</span><span class="p">(</span><span class="n">other</span><span class="p">).</span><span class="nf">sum</span> <span class="p">{</span> <span class="o">|</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="o">|</span> <span class="n">a</span> <span class="o">*</span> <span class="n">b</span> <span class="p">}</span>
</span>
            <span class="line line-19">	<span class="k">end</span>
</span>
            <span class="line line-20"><span class="k">end</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p class="no-indent">
(Again, note that this is Ruby 1.9.2.)
</p>
<p>Finally, just combine them up, and we can solve a Hamiltonian numerically.</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="k">def</span> <span class="nf">solve_hamiltonian</span> <span class="n">n</span><span class="p">,</span> <span class="n">qp0</span><span class="p">,</span> <span class="n">max_t</span><span class="p">,</span> <span class="n">dt</span><span class="p">,</span> <span class="n">hamiltonian</span>
</span>
            <span class="line line-2">	<span class="n">runge_kutta</span> <span class="n">qp0</span><span class="p">,</span> <span class="n">max_t</span><span class="p">,</span> <span class="n">dt</span><span class="p">,</span> <span class="no">CLASSIC_4TH</span><span class="p">,</span> <span class="o">-&gt;</span><span class="n">t</span><span class="p">,</span> <span class="n">qp</span> <span class="k">do</span>
</span>
            <span class="line line-3">		<span class="n">dqpdt</span> <span class="o">=</span> <span class="n">div</span> <span class="n">qp</span><span class="p">,</span> <span class="mf">1e-6</span><span class="p">,</span> <span class="o">-&gt;</span><span class="n">x</span> <span class="p">{</span> <span class="n">hamiltonian</span><span class="o">.</span><span class="p">(</span><span class="n">t</span><span class="p">,</span> <span class="n">x</span><span class="p">)</span> <span class="p">}</span>
</span>
            <span class="line line-4">		<span class="no">Vector</span><span class="p">[</span><span class="o">*</span><span class="n">dqpdt</span><span class="p">[</span><span class="n">n</span><span class="o">...</span><span class="n">n</span><span class="o">*</span><span class="mi">2</span><span class="p">],</span> <span class="o">*</span><span class="n">dqpdt</span><span class="p">[</span><span class="mi">0</span><span class="o">...</span><span class="n">n</span><span class="p">].</span><span class="nf">map</span><span class="p">(</span><span class="o">&amp;</span><span class="ss">:-@</span><span class="p">)]</span>
</span>
            <span class="line line-5">	<span class="k">end</span>
</span>
            <span class="line line-6"><span class="k">end</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p>For example, let’s simulate a double pendulum.</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="n">solve_hamiltonian</span> <span class="mi">2</span><span class="p">,</span><span class="no">Vector</span><span class="p">[</span><span class="no">PI</span><span class="o">/</span><span class="mi">2</span><span class="p">,</span><span class="mf">0.0</span><span class="p">,</span><span class="mf">0.0</span><span class="p">,</span><span class="mf">0.0</span><span class="p">],</span><span class="no">Float</span><span class="o">::</span><span class="no">INFINITY</span><span class="p">,</span><span class="mf">1e-3</span><span class="p">,</span>
</span>
            <span class="line line-2">		<span class="o">-&gt;</span><span class="n">t</span><span class="p">,(</span><span class="n">q1</span><span class="p">,</span><span class="n">q2</span><span class="p">,</span><span class="n">p1</span><span class="p">,</span><span class="n">p2</span><span class="p">){</span><span class="n">p1</span><span class="o">**</span><span class="mi">2</span><span class="o">+</span><span class="n">p2</span><span class="o">**</span><span class="mi">2</span><span class="o">/</span><span class="mi">2</span><span class="o">+</span><span class="n">cos</span><span class="p">(</span><span class="n">q1</span><span class="o">-</span><span class="n">q2</span><span class="p">)</span><span class="o">*</span><span class="n">p1</span><span class="o">*</span><span class="n">p2</span><span class="o">-</span><span class="n">cos</span><span class="p">(</span><span class="n">q1</span><span class="p">)</span><span class="o">-</span><span class="n">cos</span><span class="p">(</span><span class="n">q2</span><span class="p">)}</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<figure>
<img src="/assets/images/figures/2020-04-28-simulation-rgss/double_pendulum.gif" alt="The simulated motion of a double pendulum."/>

</figure>
<p>The codes are not complete in this post. See the <a href="/assets/codes/RungeKutta.rar">attached file</a> for details. You can open the project using <a href="https://store.steampowered.com/app/220700/RPG_Maker_VX_Ace" target="_blank" rel="external">RPG Maker VX Ace</a>. The <code>Game.exe</code> file is not the official <code>Game.exe</code> executable but the third-party improved version of it called <a href="http://cirno.blog/archives/290" target="_blank" rel="external">RGD</a> (of version 1.3.2, while the latest till now is 1.5.1).</p>]]></content><author><name>UlyssesZhan</name><email>ulysseszhan@gmail.com</email></author><category term="physics" /><category term="ruby" /><category term="rgss" /><category term="hamiltonian" /><category term="calculus" /><category term="ode" /><summary type="html"><![CDATA[Hamiltonian mechanics gives us a good way to simulate mechanical systems as long as we can get its Hamiltonian and its initial conditions. I implemented this simulation in RGSS3, the game scripting system shipped with RPG Maker VX Ace.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://ulysseszh.github.io/assets/images/covers/2020-04-28-simulation-rgss.png" /><media:content medium="image" url="https://ulysseszh.github.io/assets/images/covers/2020-04-28-simulation-rgss.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html"><![CDATA[Writing a DSL with commands split by space]]></title><link href="https://ulysseszh.github.io/programming/2020/04/27/space-split-dsl.html" rel="alternate" type="text/html" title="Writing a DSL with commands split by space" /><published>2020-04-27T05:39:39-07:00</published><updated>2020-04-27T05:39:39-07:00</updated><id>https://ulysseszh.github.io/programming/2020/04/27/space-split-dsl</id><content type="html" xml:base="https://ulysseszh.github.io/programming/2020/04/27/space-split-dsl.html"><![CDATA[<p>We want to have a DSL where we can write statements separated with space. Like this:</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="no">Robot</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
</span>
            <span class="line line-2">	<span class="n">a</span> <span class="n">b</span> <span class="n">c</span>
</span>
            <span class="line line-3">	<span class="n">d</span> <span class="n">e</span>
</span>
            <span class="line line-4">	<span class="n">f</span> <span class="n">g</span> <span class="n">h</span> <span class="n">i</span>
</span>
            <span class="line line-5">	<span class="n">j</span>
</span>
            <span class="line line-6"><span class="k">end</span><span class="p">.</span><span class="nf">run</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p class="no-indent">
outputs
</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-plain">
        <pre>
          <code>
            <span class="line line-1">Go to a
</span>
            <span class="line line-2">Go to b
</span>
            <span class="line line-3">Go to c
</span>
            <span class="line line-4">Go to d
</span>
            <span class="line line-5">Go to e
</span>
            <span class="line line-6">Go to f
</span>
            <span class="line line-7">Go to g
</span>
            <span class="line line-8">Go to h
</span>
            <span class="line line-9">Go to i
</span>
            <span class="line line-10">Go to j
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p>Since separating by space means method invocation in Ruby, we need to hack into <code>method_missing</code>.</p>
<p>I am just posting the codes and will not give it further explanation. Look into the details yourself.</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="k">class</span> <span class="nc">Robot</span>
</span>
            <span class="line line-2">	<span class="nb">attr_accessor</span> <span class="ss">:movements</span>
</span>
            <span class="line line-3">	<span class="k">def</span> <span class="nf">initialize</span> <span class="o">&amp;</span><span class="n">block</span>
</span>
            <span class="line line-4">		<span class="vi">@movements</span> <span class="o">=</span> <span class="p">[]</span>
</span>
            <span class="line line-5">		<span class="vi">@last_length</span> <span class="o">=</span> <span class="mi">0</span>
</span>
            <span class="line line-6">		<span class="nb">instance_eval</span> <span class="o">&amp;</span><span class="n">block</span> <span class="k">if</span> <span class="n">block</span>
</span>
            <span class="line line-7">		<span class="n">rearrange</span>
</span>
            <span class="line line-8">	<span class="k">end</span>
</span>
            <span class="line line-9">	<span class="k">def</span> <span class="nf">method_missing</span> <span class="nb">name</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span>
</span>
            <span class="line line-10">		<span class="k">case</span> <span class="n">args</span><span class="p">.</span><span class="nf">size</span>
</span>
            <span class="line line-11">		<span class="k">when</span> <span class="mi">0</span>
</span>
            <span class="line line-12">			<span class="n">rearrange</span>
</span>
            <span class="line line-13">			<span class="vi">@movements</span><span class="p">.</span><span class="nf">push</span> <span class="n">result</span> <span class="o">=</span> <span class="no">Movement</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="nb">name</span><span class="p">)</span>
</span>
            <span class="line line-14">			<span class="vi">@last_length</span> <span class="o">+=</span> <span class="mi">1</span>
</span>
            <span class="line line-15">			<span class="n">result</span>
</span>
            <span class="line line-16">		<span class="k">when</span> <span class="mi">1</span>
</span>
            <span class="line line-17">			<span class="vi">@movements</span><span class="p">.</span><span class="nf">push</span> <span class="n">result</span> <span class="o">=</span> <span class="no">Movement</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="nb">name</span><span class="p">)</span>
</span>
            <span class="line line-18">			<span class="vi">@last_length</span> <span class="o">+=</span> <span class="mi">1</span>
</span>
            <span class="line line-19">			<span class="n">result</span>
</span>
            <span class="line line-20">		<span class="k">else</span>
</span>
            <span class="line line-21">			<span class="k">super</span>
</span>
            <span class="line line-22">		<span class="k">end</span>
</span>
            <span class="line line-23">	<span class="k">end</span>
</span>
            <span class="line line-24">	<span class="k">def</span> <span class="nf">rearrange</span>
</span>
            <span class="line line-25">		<span class="n">last_movements</span> <span class="o">=</span> <span class="vi">@movements</span><span class="p">.</span><span class="nf">last</span> <span class="vi">@last_length</span>
</span>
            <span class="line line-26">		<span class="vi">@movements</span><span class="p">[</span><span class="vi">@movements</span><span class="p">.</span><span class="nf">size</span> <span class="o">-</span> <span class="vi">@last_length</span><span class="o">..</span><span class="p">]</span> <span class="o">=</span> <span class="n">last_movements</span><span class="p">.</span><span class="nf">reverse</span>
</span>
            <span class="line line-27">		<span class="vi">@last_length</span> <span class="o">=</span> <span class="mi">0</span>
</span>
            <span class="line line-28">	<span class="k">end</span>
</span>
            <span class="line line-29">	<span class="k">def</span> <span class="nf">run</span>
</span>
            <span class="line line-30">		<span class="nb">puts</span> <span class="vi">@movements</span>
</span>
            <span class="line line-31">	<span class="k">end</span>
</span>
            <span class="line line-32">	<span class="k">class</span> <span class="nc">Movement</span>
</span>
            <span class="line line-33">		<span class="nb">attr_accessor</span> <span class="ss">:target</span>
</span>
            <span class="line line-34">		<span class="k">def</span> <span class="nf">initialize</span> <span class="n">target</span>
</span>
            <span class="line line-35">			<span class="vi">@target</span> <span class="o">=</span> <span class="n">target</span>
</span>
            <span class="line line-36">		<span class="k">end</span>
</span>
            <span class="line line-37">		<span class="k">def</span> <span class="nf">to_s</span>
</span>
            <span class="line line-38">			<span class="s2">"Go to </span><span class="si">#@target</span><span class="s2">"</span>
</span>
            <span class="line line-39">		<span class="k">end</span>
</span>
            <span class="line line-40">	<span class="k">end</span>
</span>
            <span class="line line-41"><span class="k">end</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p>Similar tricks are used in my other Ruby project <a href="/doc/alda-rb/">alda-rb</a>. The codes can be found <a href="https://github.com/UlyssesZh/alda-rb" target="_blank" rel="external">on GitHub</a>.</p>]]></content><author><name>UlyssesZhan</name><email>ulysseszhan@gmail.com</email></author><category term="programming" /><category term="ruby" /><category term="meta programming" /><summary type="html"><![CDATA[DSL means domain-specific language. Ruby is a powerful script language in terms of building DSLs (as sublanguages of Ruby). In this article, I implemented my idea of a DSL with commands split by space. For example, you may just write <code>a b c</code> to run the commands <code>a</code>, <code>b</code>, and <code>c</code> one after another! This trick is heavily applied in my project <a href="/doc/alda-rb">alda-rb</a>. How do I achieve this?]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://ulysseszh.github.io/assets/images/covers/2020-04-27-space-split-dsl.png" /><media:content medium="image" url="https://ulysseszh.github.io/assets/images/covers/2020-04-27-space-split-dsl.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html"><![CDATA[The structure of a basic RM game]]></title><link href="https://ulysseszh.github.io/programming/2020/04/08/basic-rm-game.html" rel="alternate" type="text/html" title="The structure of a basic RM game" /><published>2020-04-07T18:28:05-07:00</published><updated>2020-04-07T18:28:05-07:00</updated><id>https://ulysseszh.github.io/programming/2020/04/08/basic-rm-game</id><content type="html" xml:base="https://ulysseszh.github.io/programming/2020/04/08/basic-rm-game.html"><![CDATA[<p><a href="https://tkool.jp/" target="_blank" rel="external">RPG Maker (RM)</a> is a tool for making games.</p>
<p>I only have experience in using RPG Maker XP, RPG Maker VX, RPG Maker VX Ace, and RPG Maker MV.</p>
<p>Games made by using RM are based on</p>
<table>
<thead>
<tr>
<th>XP</th>
<th>VX</th>
<th>VA</th>
<th>MV</th>
</tr>
</thead>
<tbody>
<tr>
<td>RGSS</td>
<td>RGSS2</td>
<td>RGSS3</td>
<td>rpg_core.js</td>
</tr>
</tbody>
</table>
<p>In most cases, when I say RGSS, I mean RGSS, RGSS2, and RGSS3. RGSS is in Ruby and rpg_core.js is in Javascript.</p>
<p>The scripts of a basic RGSS game look like</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="k">def</span> <span class="nf">start</span>
</span>
            <span class="line line-2">	<span class="c1"># some codes</span>
</span>
            <span class="line line-3"><span class="k">end</span>
</span>
            <span class="line line-4"><span class="k">def</span> <span class="nf">update</span>
</span>
            <span class="line line-5">	<span class="c1"># some codes</span>
</span>
            <span class="line line-6"><span class="k">end</span>
</span>
            <span class="line line-7">
</span>
            <span class="line line-8"><span class="n">start</span>
</span>
            <span class="line line-9"><span class="kp">loop</span> <span class="k">do</span>
</span>
            <span class="line line-10">	<span class="n">update</span>
</span>
            <span class="line line-11">	<span class="no">Input</span><span class="p">.</span><span class="nf">update</span>
</span>
            <span class="line line-12">	<span class="no">Graphics</span><span class="p">.</span><span class="nf">update</span>
</span>
            <span class="line line-13"><span class="k">end</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p>The scripts of a basic rpg_core.js game look like</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-javascript">
        <pre>
          <code>
            <span class="line line-1"><span class="kd">function</span> <span class="nf">start</span><span class="p">()</span> <span class="p">{</span>
</span>
            <span class="line line-2">	<span class="c1">// some codes</span>
</span>
            <span class="line line-3"><span class="p">}</span>
</span>
            <span class="line line-4"><span class="kd">function</span> <span class="nf">update</span><span class="p">()</span> <span class="p">{</span>
</span>
            <span class="line line-5">	<span class="c1">// some codes</span>
</span>
            <span class="line line-6"><span class="p">}</span>
</span>
            <span class="line line-7">
</span>
            <span class="line line-8"><span class="nx">Graphics</span><span class="p">.</span><span class="nf">initialize</span><span class="p">(</span><span class="mi">816</span><span class="p">,</span> <span class="mi">624</span><span class="p">,</span> <span class="dl">'</span><span class="s1">webgl</span><span class="dl">'</span><span class="p">);</span>
</span>
            <span class="line line-9"><span class="nx">Graphics</span><span class="p">.</span><span class="nx">boxWidth</span> <span class="o">=</span> <span class="mi">816</span><span class="p">;</span>
</span>
            <span class="line line-10"><span class="nx">Graphics</span><span class="p">.</span><span class="nx">boxHeight</span> <span class="o">=</span> <span class="mi">624</span><span class="p">;</span>
</span>
            <span class="line line-11"><span class="nx">WebAudio</span><span class="p">.</span><span class="nf">initialize</span><span class="p">(</span><span class="kc">false</span><span class="p">);</span>
</span>
            <span class="line line-12"><span class="nx">Input</span><span class="p">.</span><span class="nf">initialize</span><span class="p">();</span>
</span>
            <span class="line line-13"><span class="nx">TouchInput</span><span class="p">.</span><span class="nf">initialize</span><span class="p">();</span>
</span>
            <span class="line line-14"><span class="kd">var</span> <span class="nx">deltaTime</span> <span class="o">=</span> <span class="mf">1.0</span> <span class="o">/</span> <span class="mf">60.0</span><span class="p">;</span>
</span>
            <span class="line line-15"><span class="kd">var</span> <span class="nx">accumulator</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span>
</span>
            <span class="line line-16"><span class="kd">var</span> <span class="nx">currentTime</span><span class="p">;</span>
</span>
            <span class="line line-17"><span class="nb">window</span><span class="p">.</span><span class="nx">scene</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Stage</span><span class="p">();</span>
</span>
            <span class="line line-18"><span class="nf">start</span><span class="p">();</span>
</span>
            <span class="line line-19"><span class="kd">function</span> <span class="nf">performUpdate</span><span class="p">()</span> <span class="p">{</span>
</span>
            <span class="line line-20">	<span class="nx">Graphics</span><span class="p">.</span><span class="nf">tickStart</span><span class="p">();</span>
</span>
            <span class="line line-21">	<span class="kd">var</span> <span class="nx">newTime</span> <span class="o">=</span> <span class="nx">performance</span><span class="p">.</span><span class="nf">now</span><span class="p">();</span>
</span>
            <span class="line line-22">	<span class="k">if </span><span class="p">(</span><span class="nx">currentTime</span> <span class="o">===</span> <span class="kc">undefined</span><span class="p">)</span> <span class="nx">currentTime</span> <span class="o">=</span> <span class="nx">newTime</span><span class="p">;</span>
</span>
            <span class="line line-23">	<span class="kd">var</span> <span class="nx">fTime</span> <span class="o">=</span> <span class="p">((</span><span class="nx">newTime</span> <span class="o">-</span> <span class="nx">currentTime</span><span class="p">)</span> <span class="o">/</span> <span class="mi">1000</span><span class="p">).</span><span class="nf">clamp</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mf">0.25</span><span class="p">);</span>
</span>
            <span class="line line-24">	<span class="nx">currentTime</span> <span class="o">=</span> <span class="nx">newTime</span><span class="p">;</span>
</span>
            <span class="line line-25">	<span class="nx">accumulator</span> <span class="o">+=</span> <span class="nx">fTime</span><span class="p">;</span>
</span>
            <span class="line line-26">	<span class="k">while </span><span class="p">(</span><span class="nx">accumulator</span> <span class="o">&gt;=</span> <span class="nx">deltaTime</span><span class="p">)</span> <span class="p">{</span>
</span>
            <span class="line line-27">		<span class="nx">Input</span><span class="p">.</span><span class="nf">update</span><span class="p">();</span>
</span>
            <span class="line line-28">		<span class="nx">TouchInput</span><span class="p">.</span><span class="nf">update</span><span class="p">();</span>
</span>
            <span class="line line-29">		<span class="nf">update</span><span class="p">();</span>
</span>
            <span class="line line-30">		<span class="nx">accumulator</span> <span class="o">-=</span> <span class="nx">deltaTime</span><span class="p">;</span>
</span>
            <span class="line line-31">	<span class="p">}</span>
</span>
            <span class="line line-32">	<span class="nx">Graphics</span><span class="p">.</span><span class="nf">render</span><span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">scene</span><span class="p">);</span>
</span>
            <span class="line line-33">	<span class="nf">requestAnimationFrame</span><span class="p">(</span><span class="nx">performUpdate</span><span class="p">);</span>
</span>
            <span class="line line-34">	<span class="nx">Graphics</span><span class="p">.</span><span class="nf">tickEnd</span><span class="p">();</span>
</span>
            <span class="line line-35"><span class="p">}</span>
</span>
            <span class="line line-36"><span class="nf">performUpdate</span><span class="p">();</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p>There is a simple rpg_core.js game written by me which can be accessed <a href="/rpg/hello/">here</a>. You can look at its source code by using your browser.</p>
<p>RM also provides a lot of scripts serving as making RPG. There is a simple RPG built by me which can be accessed <a href="/rpg/test/">here</a>.</p>
<p>The source codes of RGSS are secret, but those of rpg_core.js are not a secret and can be seen at <a href="https://github.com/rpgtkoolmv/corescript/" target="_blank" rel="external">its GitHub repo</a>.</p>]]></content><author><name>UlyssesZhan</name><email>ulysseszhan@gmail.com</email></author><category term="programming" /><category term="ruby" /><category term="javascript" /><category term="rgss" /><summary type="html"><![CDATA[In this article, I present minimal examples of a RM game. They only illustrate the basic concepts of how a RM game is structured and what is the running logic of it.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://ulysseszh.github.io/assets/images/covers/2020-04-08-basic-rm-game.png" /><media:content medium="image" url="https://ulysseszh.github.io/assets/images/covers/2020-04-08-basic-rm-game.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html"><![CDATA[Monkey-patching graciously]]></title><link href="https://ulysseszh.github.io/programming/2020/02/09/ruby-patch-def.html" rel="alternate" type="text/html" title="Monkey-patching graciously" /><published>2020-02-08T21:16:31-08:00</published><updated>2020-02-08T21:16:31-08:00</updated><id>https://ulysseszh.github.io/programming/2020/02/09/ruby-patch-def</id><content type="html" xml:base="https://ulysseszh.github.io/programming/2020/02/09/ruby-patch-def.html"><![CDATA[<p>I am going to show how to monkey-patch graciously using <a href="https://www.ruby-lang.org/" target="_blank" rel="external">Ruby</a>.</p>
<p>The original idea is to implement a method <code>Module#def_after</code> so that I can easily make something to be done after the original method. Like this:</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="k">class</span> <span class="nc">Foo</span>
</span>
            <span class="line line-2">	<span class="k">def</span> <span class="nf">bar</span>
</span>
            <span class="line line-3">		<span class="nb">print</span> <span class="s1">'before'</span>
</span>
            <span class="line line-4">	<span class="k">end</span>
</span>
            <span class="line line-5"><span class="k">end</span>
</span>
            <span class="line line-6">
</span>
            <span class="line line-7"><span class="k">class</span> <span class="nc">Foo</span>
</span>
            <span class="line line-8">	<span class="n">def_after</span> <span class="ss">:bar</span> <span class="k">do</span>
</span>
            <span class="line line-9">		<span class="nb">puts</span> <span class="s1">' &amp; after'</span>
</span>
            <span class="line line-10">	<span class="k">end</span>
</span>
            <span class="line line-11"><span class="k">end</span>
</span>
            <span class="line line-12">
</span>
            <span class="line line-13"><span class="no">Foo</span><span class="p">.</span><span class="nf">new</span><span class="p">.</span><span class="nf">bar</span> <span class="c1"># =&gt; before &amp; after</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p class="no-indent">
The implementation is a little easy:
</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="k">class</span> <span class="nc">Module</span>
</span>
            <span class="line line-2">	<span class="k">def</span> <span class="nf">def_after</span> <span class="n">method_name</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">refine_block</span>
</span>
            <span class="line line-3">		<span class="n">old</span> <span class="o">=</span> <span class="nb">instance_method</span> <span class="n">method_name</span>
</span>
            <span class="line line-4">		<span class="n">define_method</span> <span class="n">method_name</span> <span class="k">do</span> <span class="o">|*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span><span class="o">|</span>
</span>
            <span class="line line-5">			<span class="n">old</span><span class="p">.</span><span class="nf">bind_call</span> <span class="nb">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span>
</span>
            <span class="line line-6">			<span class="n">refine_block</span><span class="o">.</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span><span class="p">)</span>
</span>
            <span class="line line-7">		<span class="k">end</span>
</span>
            <span class="line line-8">	<span class="k">end</span>
</span>
            <span class="line line-9"><span class="k">end</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p class="no-indent">
However, there is a little problem. The <code>self</code> in <code>refine_block</code> depends on how and where <code>refine_block</code> is defined instead of just being the instance receiving the method.
</p>
<p>Since an instance method (<code>UnboundMethod</code> object) defined in a <code>Module</code> can <code>bind</code> any other object, we can use <code>Module#define_method</code> and send <code>refine_block</code> as a block parameter, and then bind the instance method to <code>self</code>:</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="k">class</span> <span class="nc">Proc</span>
</span>
            <span class="line line-2">	<span class="k">def</span> <span class="nf">bind</span> <span class="n">receiver</span>
</span>
            <span class="line line-3">		<span class="no">Module</span><span class="p">.</span><span class="nf">new</span><span class="p">.</span><span class="nf">module_exec</span> <span class="nb">self</span> <span class="k">do</span> <span class="o">|</span><span class="n">block</span><span class="o">|</span>
</span>
            <span class="line line-4">			<span class="nb">instance_method</span> <span class="n">define_method</span> <span class="ss">:_</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span>
</span>
            <span class="line line-5">		<span class="k">end</span><span class="p">.</span><span class="nf">bind</span> <span class="n">receiver</span>
</span>
            <span class="line line-6">	<span class="k">end</span>
</span>
            <span class="line line-7">	<span class="k">def</span> <span class="nf">bind_call</span> <span class="n">receiver</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span>
</span>
            <span class="line line-8">		<span class="n">bind</span><span class="p">(</span><span class="n">receiver</span><span class="p">)</span><span class="o">.</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span><span class="p">)</span>
</span>
            <span class="line line-9">	<span class="k">end</span>
</span>
            <span class="line line-10"><span class="k">end</span>
</span>
            <span class="line line-11"><span class="k">class</span> <span class="nc">Module</span>
</span>
            <span class="line line-12">	<span class="k">def</span> <span class="nf">def_after</span> <span class="n">method_name</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">refine_block</span>
</span>
            <span class="line line-13">		<span class="n">old</span> <span class="o">=</span> <span class="nb">instance_method</span> <span class="n">method_name</span>
</span>
            <span class="line line-14">		<span class="n">define_method</span> <span class="n">method_name</span> <span class="k">do</span> <span class="o">|*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span><span class="o">|</span>
</span>
            <span class="line line-15">			<span class="n">old</span><span class="p">.</span><span class="nf">bind_call</span> <span class="nb">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span>
</span>
            <span class="line line-16">			<span class="n">refine_block</span><span class="p">.</span><span class="nf">bind_call</span> <span class="nb">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span>
</span>
            <span class="line line-17">		<span class="k">end</span>
</span>
            <span class="line line-18">	<span class="k">end</span>
</span>
            <span class="line line-19"><span class="k">end</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p class="no-indent">
The <code>self</code> can successfully be converted. You can test it yourself.
</p>
<p>Here is still a problem. When the new instance method is defined, its visibility is <code>public</code>, while the original visibility may be <code>private</code> or <code>protected</code>.</p>
<p>Use the following means to get the visibility beforehand and set the visibility afterward:</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="k">class</span> <span class="nc">Module</span>
</span>
            <span class="line line-2">	<span class="k">def</span> <span class="nf">method_visibility</span> <span class="n">method_name</span>
</span>
            <span class="line line-3">		<span class="sx">%i[public protected private]</span><span class="p">.</span><span class="nf">find</span> <span class="k">do</span> <span class="o">|</span><span class="n">visibility</span><span class="o">|</span>
</span>
            <span class="line line-4">			<span class="nb">__send__</span> <span class="ss">:"</span><span class="si">#{</span><span class="n">visibility</span><span class="si">}</span><span class="ss">_method_defined?"</span><span class="p">,</span> <span class="n">method_name</span>
</span>
            <span class="line line-5">		<span class="k">end</span>
</span>
            <span class="line line-6">	<span class="k">end</span>
</span>
            <span class="line line-7">	<span class="k">def</span> <span class="nf">def_after</span> <span class="n">method_name</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">refine_block</span>
</span>
            <span class="line line-8">		<span class="n">visibility</span> <span class="o">=</span> <span class="n">method_visibility</span> <span class="n">method_name</span>
</span>
            <span class="line line-9">		<span class="n">old</span> <span class="o">=</span> <span class="nb">instance_method</span> <span class="n">method_name</span>
</span>
            <span class="line line-10">		<span class="n">define_method</span> <span class="n">method_name</span> <span class="k">do</span> <span class="o">|*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span><span class="o">|</span>
</span>
            <span class="line line-11">			<span class="n">old</span><span class="p">.</span><span class="nf">bind_call</span> <span class="nb">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span>
</span>
            <span class="line line-12">			<span class="n">refine_block</span><span class="p">.</span><span class="nf">bind_call</span> <span class="nb">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span>
</span>
            <span class="line line-13">		<span class="k">end</span>
</span>
            <span class="line line-14">		<span class="nb">__send__</span> <span class="n">visibility</span><span class="p">,</span> <span class="n">method_name</span>
</span>
            <span class="line line-15">	<span class="k">end</span>
</span>
            <span class="line line-16"><span class="k">end</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p>There can be some improvement. If we need to refine a singleton method, calling <code>def_after</code> on its <code>singleton_class</code> will lead to calling <code>obj.singleton_class.instance_method(sym).bind_call(obj, *)</code>, which is way too complex. The straightforward way to do it is to call <code>obj.method(sym).call(*)</code>.</p>
<p>With this inspiration, we can implement <code>Object#def_after</code>:</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="k">class</span> <span class="nc">Object</span>
</span>
            <span class="line line-2">	<span class="k">def</span> <span class="nf">def_after</span> <span class="n">method_name</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">refine_block</span>
</span>
            <span class="line line-3">		<span class="n">visibility</span> <span class="o">=</span> <span class="n">singleton_class</span><span class="p">.</span><span class="nf">method_visibility</span> <span class="n">method_name</span>
</span>
            <span class="line line-4">		<span class="n">old</span> <span class="o">=</span> <span class="nb">method</span> <span class="n">method_name</span>
</span>
            <span class="line line-5">		<span class="n">define_singleton_method</span> <span class="n">method_name</span> <span class="k">do</span> <span class="o">|*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span><span class="o">|</span>
</span>
            <span class="line line-6">			<span class="n">old</span><span class="o">.</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span><span class="p">)</span>
</span>
            <span class="line line-7">			<span class="n">refine_block</span><span class="p">.</span><span class="nf">bind_call</span> <span class="nb">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span>
</span>
            <span class="line line-8">		<span class="k">end</span>
</span>
            <span class="line line-9">		<span class="n">singleton_class</span><span class="p">.</span><span class="nf">__send__</span> <span class="n">visibility</span><span class="p">,</span> <span class="n">method_name</span>
</span>
            <span class="line line-10">	<span class="k">end</span>
</span>
            <span class="line line-11"><span class="k">end</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p>Then there comes a new problem. A <code>Module</code> also has singleton methods, while <code>Module#def_after</code> can only change its instance methods instead of its singleton methods. The way to solve this is to judge whether <code>is_a? Module</code> in <code>Object#def_after</code>, and add a keyword argument <code>singleton</code>:</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="k">class</span> <span class="nc">Object</span>
</span>
            <span class="line line-2">	<span class="k">def</span> <span class="nf">def_after</span> <span class="n">method_name</span><span class="p">,</span> <span class="ss">singleton: </span><span class="kp">false</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">refine_block</span>
</span>
            <span class="line line-3">		<span class="n">singleton</span> <span class="o">||=</span> <span class="o">!</span><span class="nb">is_a?</span><span class="p">(</span><span class="no">Module</span><span class="p">)</span>
</span>
            <span class="line line-4">		<span class="c1"># mod: the module containing the old method</span>
</span>
            <span class="line line-5">		<span class="c1"># get_method: the method to get the Method/UnboundMethod obj</span>
</span>
            <span class="line line-6">		<span class="c1"># def_method: the method to define a new method</span>
</span>
            <span class="line line-7">		<span class="n">mod</span><span class="p">,</span> <span class="n">get_method</span><span class="p">,</span> <span class="n">def_method</span> <span class="o">=</span> <span class="n">singleton</span> <span class="p">?</span>
</span>
            <span class="line line-8">				<span class="p">[</span><span class="n">singleton_class</span><span class="p">,</span> <span class="nb">method</span><span class="p">(</span><span class="ss">:method</span><span class="p">),</span> <span class="nb">method</span><span class="p">(</span><span class="ss">:define_singleton_method</span><span class="p">)]</span> <span class="p">:</span>
</span>
            <span class="line line-9">				<span class="p">[</span><span class="nb">self</span><span class="p">,</span> <span class="nb">method</span><span class="p">(</span><span class="ss">:instance_method</span><span class="p">),</span> <span class="nb">method</span><span class="p">(</span><span class="ss">:define_method</span><span class="p">)]</span>
</span>
            <span class="line line-10">		<span class="c1"># get visibility</span>
</span>
            <span class="line line-11">		<span class="n">visibility</span> <span class="o">=</span> <span class="n">mod</span><span class="p">.</span><span class="nf">method_visibility</span> <span class="n">method_name</span>
</span>
            <span class="line line-12">		<span class="c1"># get old</span>
</span>
            <span class="line line-13">		<span class="n">old</span> <span class="o">=</span> <span class="n">get_method</span><span class="o">.</span><span class="p">(</span><span class="n">method_name</span><span class="p">)</span>
</span>
            <span class="line line-14">		<span class="c1"># override</span>
</span>
            <span class="line line-15">		<span class="n">def_method</span><span class="o">.</span><span class="p">(</span><span class="n">method_name</span><span class="p">)</span> <span class="k">do</span> <span class="o">|*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span><span class="o">|</span>
</span>
            <span class="line line-16">			<span class="n">old</span> <span class="o">=</span> <span class="n">old</span><span class="p">.</span><span class="nf">bind</span> <span class="nb">self</span> <span class="k">unless</span> <span class="n">old</span><span class="p">.</span><span class="nf">is_a?</span> <span class="no">Method</span>
</span>
            <span class="line line-17">			<span class="n">old</span><span class="o">.</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span><span class="p">)</span>
</span>
            <span class="line line-18">			<span class="n">refine_block</span><span class="p">.</span><span class="nf">bind_call</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span>
</span>
            <span class="line line-19">		<span class="k">end</span>
</span>
            <span class="line line-20">		<span class="c1"># set visibility</span>
</span>
            <span class="line line-21">		<span class="n">mod</span><span class="p">.</span><span class="nf">__send__</span> <span class="n">visibility</span><span class="p">,</span> <span class="n">method_name</span>
</span>
            <span class="line line-22">	<span class="k">end</span>
</span>
            <span class="line line-23"><span class="k">end</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p class="no-indent">
What about parsing a callable object as an argument instead of through <code>refine_block</code>? Parsing a <code>Symbol</code> can also be useful. Like this:
</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="no">Object</span><span class="p">.</span><span class="nf">def_after</span> <span class="ss">:display</span><span class="p">,</span> <span class="ss">:puts</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p class="no-indent">
Then <code>Object#def_after</code> will be a little complex:
</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="k">class</span> <span class="nc">Object</span>
</span>
            <span class="line line-2">	<span class="c1"># pat: when refine_block is nil, it is used to represent a refinement</span>
</span>
            <span class="line line-3">	<span class="c1"># singleton: force singleton when self is a Module</span>
</span>
            <span class="line line-4">	<span class="k">def</span> <span class="nf">def_after</span> <span class="n">method_name</span><span class="p">,</span> <span class="n">pat</span> <span class="o">=</span> <span class="kp">nil</span> <span class="p">,</span> <span class="ss">singleton: </span><span class="kp">false</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">refine_block</span>
</span>
            <span class="line line-5">		<span class="n">singleton</span> <span class="o">||=</span> <span class="o">!</span><span class="nb">is_a?</span><span class="p">(</span><span class="no">Module</span><span class="p">)</span>
</span>
            <span class="line line-6">		<span class="c1"># mod: the module containing the old method</span>
</span>
            <span class="line line-7">		<span class="c1"># get_method: the method to get the Method/UnboundMethod obj</span>
</span>
            <span class="line line-8">		<span class="c1"># def_method: the method to define a new method</span>
</span>
            <span class="line line-9">		<span class="n">mod</span><span class="p">,</span> <span class="n">get_method</span><span class="p">,</span> <span class="n">def_method</span> <span class="o">=</span> <span class="n">singleton</span> <span class="p">?</span>
</span>
            <span class="line line-10">				<span class="p">[</span><span class="n">singleton_class</span><span class="p">,</span> <span class="nb">method</span><span class="p">(</span><span class="ss">:method</span><span class="p">),</span> <span class="nb">method</span><span class="p">(</span><span class="ss">:define_singleton_method</span><span class="p">)]</span> <span class="p">:</span>
</span>
            <span class="line line-11">				<span class="p">[</span><span class="nb">self</span><span class="p">,</span> <span class="nb">method</span><span class="p">(</span><span class="ss">:instance_method</span><span class="p">),</span> <span class="nb">method</span><span class="p">(</span><span class="ss">:define_method</span><span class="p">)]</span>
</span>
            <span class="line line-12">		<span class="c1"># get visibility</span>
</span>
            <span class="line line-13">		<span class="n">visibility</span> <span class="o">=</span> <span class="n">mod</span><span class="p">.</span><span class="nf">method_visibility</span> <span class="n">method_name</span>
</span>
            <span class="line line-14">		<span class="c1"># get pat</span>
</span>
            <span class="line line-15">		<span class="n">pat</span> <span class="o">=</span> <span class="n">refine_block</span> <span class="o">||</span> <span class="p">{</span>
</span>
            <span class="line line-16">			<span class="ss">to_sym:  </span><span class="o">-&gt;</span><span class="n">symbol</span> <span class="p">{</span> <span class="n">get_method</span><span class="o">.</span><span class="p">(</span><span class="n">symbol</span><span class="p">.</span><span class="nf">to_sym</span><span class="p">)</span> <span class="p">},</span>
</span>
            <span class="line line-17">			<span class="ss">to_proc: :to_proc</span><span class="p">.</span><span class="nf">to_proc</span><span class="p">,</span>
</span>
            <span class="line line-18">			<span class="ss">call:    </span><span class="o">-&gt;</span><span class="n">callable</span> <span class="p">{</span> <span class="n">callable</span><span class="p">.</span><span class="nf">method</span> <span class="ss">:call</span> <span class="p">}</span>
</span>
            <span class="line line-19">		<span class="p">}.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">duck</span><span class="p">,</span> <span class="n">out</span><span class="o">|</span>
</span>
            <span class="line line-20">			<span class="k">break</span> <span class="n">out</span><span class="o">.</span><span class="p">(</span><span class="n">pat</span><span class="p">)</span> <span class="k">if</span> <span class="n">pat</span><span class="p">.</span><span class="nf">respond_to?</span> <span class="n">duck</span>
</span>
            <span class="line line-21">		<span class="k">end</span>
</span>
            <span class="line line-22">		<span class="c1"># get old</span>
</span>
            <span class="line line-23">		<span class="n">old</span> <span class="o">=</span> <span class="n">get_method</span><span class="o">.</span><span class="p">(</span><span class="n">method_name</span><span class="p">)</span>
</span>
            <span class="line line-24">		<span class="c1"># override</span>
</span>
            <span class="line line-25">		<span class="n">def_method</span><span class="o">.</span><span class="p">(</span><span class="n">method_name</span><span class="p">)</span> <span class="k">do</span> <span class="o">|*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span><span class="o">|</span>
</span>
            <span class="line line-26">			<span class="c1"># bind old</span>
</span>
            <span class="line line-27">			<span class="n">old</span> <span class="o">=</span> <span class="n">old</span><span class="p">.</span><span class="nf">bind</span> <span class="nb">self</span> <span class="k">unless</span> <span class="n">old</span><span class="p">.</span><span class="nf">is_a?</span> <span class="no">Method</span>
</span>
            <span class="line line-28">			<span class="c1"># bind pat</span>
</span>
            <span class="line line-29">			<span class="n">pat</span> <span class="o">=</span> <span class="n">pat</span><span class="p">.</span><span class="nf">bind</span> <span class="nb">self</span> <span class="k">unless</span> <span class="n">pat</span><span class="p">.</span><span class="nf">is_a?</span> <span class="no">Method</span>
</span>
            <span class="line line-30">			<span class="c1"># call the new method</span>
</span>
            <span class="line line-31">			<span class="n">old</span><span class="o">.</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span><span class="p">)</span>
</span>
            <span class="line line-32">			<span class="n">pat</span><span class="o">.</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span><span class="p">)</span>
</span>
            <span class="line line-33">		<span class="k">end</span>
</span>
            <span class="line line-34">		<span class="c1"># set visibility</span>
</span>
            <span class="line line-35">		<span class="n">mod</span><span class="p">.</span><span class="nf">__send__</span> <span class="n">visibility</span><span class="p">,</span> <span class="n">method_name</span>
</span>
            <span class="line line-36">	<span class="k">end</span>
</span>
            <span class="line line-37"><span class="k">end</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p>We are still not satisfied. We need to define a lot of methods like <code>def_after</code>, such as <code>def_before</code>, <code>def_if</code>… Maybe we should define <code>Object::def_</code> and use it like this:</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="k">class</span> <span class="nc">Object</span>
</span>
            <span class="line line-2">	<span class="c1"># use this binding to eval to avoid excessive local variables</span>
</span>
            <span class="line line-3">	<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">class_binding</span>
</span>
            <span class="line line-4">		<span class="nb">binding</span>
</span>
            <span class="line line-5">	<span class="k">end</span>
</span>
            <span class="line line-6">	<span class="p">{</span>
</span>
            <span class="line line-7">		<span class="ss">after:  </span><span class="s1">'result = old.(*); pat.(*); result'</span><span class="p">,</span>
</span>
            <span class="line line-8">		<span class="ss">after!: </span><span class="s1">'old.(*); pat.(*)'</span><span class="p">,</span>
</span>
            <span class="line line-9">		<span class="ss">before: </span><span class="s1">'pat.(*); old.(*)'</span><span class="p">,</span>
</span>
            <span class="line line-10">		<span class="ss">with:   </span><span class="s1">'pat.(old.(*), *)'</span><span class="p">,</span>
</span>
            <span class="line line-11">		<span class="ss">chain:  </span><span class="s1">'pat.(old, *)'</span><span class="p">,</span>
</span>
            <span class="line line-12">		<span class="ss">and:    </span><span class="s1">'old.(*) &amp;&amp; pat.(*)'</span><span class="p">,</span>
</span>
            <span class="line line-13">		<span class="ss">or:     </span><span class="s1">'old.(*) || pat.(*)'</span><span class="p">,</span>
</span>
            <span class="line line-14">		<span class="ss">if:     </span><span class="s1">'pat.(*) &amp;&amp; old.(*)'</span><span class="p">,</span>
</span>
            <span class="line line-15">		<span class="ss">unless: </span><span class="s1">'pat.(*) || old.(*)'</span>
</span>
            <span class="line line-16">	<span class="p">}.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">sym</span><span class="p">,</span> <span class="n">code</span><span class="o">|</span>
</span>
            <span class="line line-17">		<span class="n">str</span> <span class="o">=</span> <span class="s2">"def_(:</span><span class="si">#{</span><span class="n">sym</span><span class="si">}</span><span class="s2">) { |old, pat, *| </span><span class="si">#{</span><span class="n">code</span><span class="si">}</span><span class="s2"> }"</span>
</span>
            <span class="line line-18">		<span class="n">str</span><span class="p">.</span><span class="nf">gsub!</span> <span class="p">?</span><span class="o">*</span><span class="p">,</span> <span class="s1">'*args, **opts, &amp;block'</span>
</span>
            <span class="line line-19">		<span class="n">class_binding</span><span class="p">.</span><span class="nf">eval</span> <span class="n">str</span>
</span>
            <span class="line line-20">	<span class="k">end</span>
</span>
            <span class="line line-21">	<span class="n">singleton_class</span><span class="p">.</span><span class="nf">undef_method</span> <span class="ss">:def_</span><span class="p">,</span> <span class="p">:</span><span class="n">class_binding</span>
</span>
            <span class="line line-22"><span class="k">end</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p>The main difficulty is to implement <code>Object::def_</code>. We can accomplish this just by editing the <code>Object#def_after</code> we defined before:</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="k">class</span> <span class="nc">Object</span>
</span>
            <span class="line line-2">	<span class="c1"># the method is going to be undefined soon</span>
</span>
            <span class="line line-3">	<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">def_</span> <span class="n">sym</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">def_block</span>
</span>
            <span class="line line-4">		<span class="c1"># pat: when refine_block is nil, it is used to represent a refinement</span>
</span>
            <span class="line line-5">		<span class="c1"># singleton: force singleton when self is a Module</span>
</span>
            <span class="line line-6">		<span class="n">define_method</span> <span class="ss">:"def_</span><span class="si">#{</span><span class="n">sym</span><span class="si">}</span><span class="ss">"</span> <span class="k">do</span> <span class="o">|</span><span class="n">method_name</span><span class="p">,</span> <span class="n">pat</span> <span class="o">=</span> <span class="kp">nil</span><span class="p">,</span> <span class="ss">singleton: </span><span class="kp">false</span><span class="p">,</span>
</span>
            <span class="line line-7">		                                <span class="o">&amp;</span><span class="n">refine_block</span><span class="o">|</span>
</span>
            <span class="line line-8">			<span class="n">singleton</span> <span class="o">||=</span> <span class="o">!</span><span class="nb">is_a?</span><span class="p">(</span><span class="no">Module</span><span class="p">)</span>
</span>
            <span class="line line-9">			<span class="c1"># mod: the module containing the old method</span>
</span>
            <span class="line line-10">			<span class="c1"># get_method: the method to get the Method/UnboundMethod obj</span>
</span>
            <span class="line line-11">			<span class="c1"># def_method: the method to define a new method</span>
</span>
            <span class="line line-12">			<span class="n">mod</span><span class="p">,</span> <span class="n">get_method</span><span class="p">,</span> <span class="n">def_method</span> <span class="o">=</span> <span class="n">singleton</span> <span class="p">?</span>
</span>
            <span class="line line-13">					<span class="p">[</span><span class="n">singleton_class</span><span class="p">,</span> <span class="nb">method</span><span class="p">(</span><span class="ss">:method</span><span class="p">),</span> <span class="nb">method</span><span class="p">(</span><span class="ss">:define_singleton_method</span><span class="p">)]</span> <span class="p">:</span>
</span>
            <span class="line line-14">					<span class="p">[</span><span class="nb">self</span><span class="p">,</span> <span class="nb">method</span><span class="p">(</span><span class="ss">:instance_method</span><span class="p">),</span> <span class="nb">method</span><span class="p">(</span><span class="ss">:define_method</span><span class="p">)]</span>
</span>
            <span class="line line-15">			<span class="c1"># get visibility</span>
</span>
            <span class="line line-16">			<span class="n">visibility</span> <span class="o">=</span> <span class="n">mod</span><span class="p">.</span><span class="nf">method_visibility</span> <span class="n">method_name</span>
</span>
            <span class="line line-17">			<span class="c1"># get pat</span>
</span>
            <span class="line line-18">			<span class="n">pat</span> <span class="o">=</span> <span class="n">refine_block</span> <span class="o">||</span> <span class="p">{</span>
</span>
            <span class="line line-19">				<span class="ss">to_sym:  </span><span class="o">-&gt;</span><span class="n">symbol</span> <span class="p">{</span> <span class="n">get_method</span><span class="o">.</span><span class="p">(</span><span class="n">symbol</span><span class="p">.</span><span class="nf">to_sym</span><span class="p">)</span> <span class="p">},</span>
</span>
            <span class="line line-20">				<span class="ss">to_proc: :to_proc</span><span class="p">.</span><span class="nf">to_proc</span><span class="p">,</span>
</span>
            <span class="line line-21">				<span class="ss">call:    </span><span class="o">-&gt;</span><span class="n">callable</span> <span class="p">{</span> <span class="n">callable</span><span class="p">.</span><span class="nf">method</span> <span class="ss">:call</span> <span class="p">}</span>
</span>
            <span class="line line-22">			<span class="p">}.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">duck</span><span class="p">,</span> <span class="n">out</span><span class="o">|</span>
</span>
            <span class="line line-23">				<span class="k">break</span> <span class="n">out</span><span class="o">.</span><span class="p">(</span><span class="n">pat</span><span class="p">)</span> <span class="k">if</span> <span class="n">pat</span><span class="p">.</span><span class="nf">respond_to?</span> <span class="n">duck</span>
</span>
            <span class="line line-24">			<span class="k">end</span>
</span>
            <span class="line line-25">			<span class="c1"># get old</span>
</span>
            <span class="line line-26">			<span class="n">old</span> <span class="o">=</span> <span class="n">get_method</span><span class="o">.</span><span class="p">(</span><span class="n">method_name</span><span class="p">)</span>
</span>
            <span class="line line-27">			<span class="c1"># override</span>
</span>
            <span class="line line-28">			<span class="n">def_method</span><span class="o">.</span><span class="p">(</span><span class="n">method_name</span><span class="p">)</span> <span class="k">do</span> <span class="o">|*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span><span class="o">|</span>
</span>
            <span class="line line-29">				<span class="c1"># bind old</span>
</span>
            <span class="line line-30">				<span class="n">old</span> <span class="o">=</span> <span class="n">old</span><span class="p">.</span><span class="nf">bind</span> <span class="nb">self</span> <span class="k">unless</span> <span class="n">old</span><span class="p">.</span><span class="nf">is_a?</span> <span class="no">Method</span>
</span>
            <span class="line line-31">				<span class="c1"># bind pat</span>
</span>
            <span class="line line-32">				<span class="n">pat</span> <span class="o">=</span> <span class="n">pat</span><span class="p">.</span><span class="nf">bind</span> <span class="nb">self</span> <span class="k">unless</span> <span class="n">pat</span><span class="p">.</span><span class="nf">is_a?</span> <span class="no">Method</span>
</span>
            <span class="line line-33">				<span class="c1"># call the new method</span>
</span>
            <span class="line line-34">				<span class="n">def_block</span><span class="o">.</span><span class="p">(</span><span class="n">old</span><span class="p">,</span> <span class="n">pat</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span><span class="p">)</span>
</span>
            <span class="line line-35">			<span class="k">end</span>
</span>
            <span class="line line-36">			<span class="c1"># set visibility</span>
</span>
            <span class="line line-37">			<span class="n">mod</span><span class="p">.</span><span class="nf">__send__</span> <span class="n">visibility</span><span class="p">,</span> <span class="n">method_name</span>
</span>
            <span class="line line-38">		<span class="k">end</span>
</span>
            <span class="line line-39">	<span class="k">end</span>
</span>
            <span class="line line-40"><span class="k">end</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p>The final source code can be found <a href="/assets/codes/patch_def.rb">here</a>.</p>
<p>The reason why I do not use <code>Module#refine</code> and <code>Module#using</code> is that they currently have too much limitations and even bugs. I have already found as many as two bugs (<a href="https://bugs.ruby-lang.org/issues/16107" target="_blank" rel="external">#16107</a> and <a href="https://bugs.ruby-lang.org/issues/16617" target="_blank" rel="external">#16617</a>). Although both of them have been fixed (or will be fixed), I cannot be sure that there will not be further and fatal bugs. I do not think these features are very reliable in recent Ruby versions.</p>]]></content><author><name>UlyssesZhan</name><email>ulysseszhan@gmail.com</email></author><category term="programming" /><category term="ruby" /><category term="meta programming" /><category term="long paper" /><summary type="html"><![CDATA[Monkey-patching is a powerful tool in programming. In this article, I used techniques of Ruby metaprogramming to define a series of methods <code>def_after</code>, <code>def_before</code>, etc. to help monkey-patching. They look graciously in that we can use it to shorten the codes for monkey-patching (avoiding aliasing and repeating codes).]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://ulysseszh.github.io/assets/images/covers/2020-02-09-ruby-patch-def.png" /><media:content medium="image" url="https://ulysseszh.github.io/assets/images/covers/2020-02-09-ruby-patch-def.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>