aboutsummaryrefslogtreecommitdiffhomepage
path: root/services/nuldoc/public/blog/posts/2025-11-27/anybatross-writeup
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-02-01 00:49:15 +0900
committernsfisis <nsfisis@gmail.com>2026-02-01 00:49:19 +0900
commit6dedddc545e2f1930bdc2256784eb1551bd4231d (patch)
tree75fcb5a6043dc0f2c31b098bf3cfd17a2b938599 /services/nuldoc/public/blog/posts/2025-11-27/anybatross-writeup
parentd08e3edb65b215152aa26e3518fb2f2cd7071c4b (diff)
downloadnsfisis.dev-6dedddc545e2f1930bdc2256784eb1551bd4231d.tar.gz
nsfisis.dev-6dedddc545e2f1930bdc2256784eb1551bd4231d.tar.zst
nsfisis.dev-6dedddc545e2f1930bdc2256784eb1551bd4231d.zip
feat(nuldoc): rewrite nuldoc in Ruby
Diffstat (limited to 'services/nuldoc/public/blog/posts/2025-11-27/anybatross-writeup')
-rw-r--r--services/nuldoc/public/blog/posts/2025-11-27/anybatross-writeup/index.html92
1 files changed, 52 insertions, 40 deletions
diff --git a/services/nuldoc/public/blog/posts/2025-11-27/anybatross-writeup/index.html b/services/nuldoc/public/blog/posts/2025-11-27/anybatross-writeup/index.html
index f106611e..d4e8f183 100644
--- a/services/nuldoc/public/blog/posts/2025-11-27/anybatross-writeup/index.html
+++ b/services/nuldoc/public/blog/posts/2025-11-27/anybatross-writeup/index.html
@@ -132,7 +132,8 @@
<section id="section--hole-1--answer">
<h3><a href="#section--hole-1--answer">回答 (45 byte)</a></h3>
<div class="codeblock">
- <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#005CC5">print</span><span style="color:#24292E">$a+=$\=</span><span style="color:#005CC5">y</span><span style="color:#032F62">/8B/0/</span><span style="color:#24292E">+</span><span style="color:#005CC5">y</span><span style="color:#032F62">/0469ADO-R//</span><span style="color:#24292E">.$/,</span><span style="color:#032F62">","</span><span style="color:#D73A49">for</span><span style="color:#24292E">&#x3C;></span></span></code></pre>
+ <pre class="highlight" style="background-color:#f5f5f5"><code><span style="color: #cf222e">print</span><span style="color: #0550ae">$a</span><span style="color: #0550ae">+=</span><span style="color: #0550ae">$\</span><span style="color: #0550ae">=</span><span style="color: #116329">y/8B/0/</span><span style="color: #0550ae">+</span><span style="color: #116329">y/0469ADO-R//</span><span style="color: #0550ae">.</span><span style="color: #0550ae">$/</span><span style="color: #24292f;background-color: #f6f8fa">,"</span><span style="color: #0a3069">,</span><span style="color: #24292f;background-color: #f6f8fa">"</span><span style="color: #cf222e">for</span><span style="color: #0550ae">&lt;&gt;</span>
+</code></pre>
</div>
<p>
Hole 1 については同一言語・同一スコアの回答が複数あるので詳細は省略する。
@@ -150,10 +151,11 @@
最終スコアを見ると 4 位タイ (107 byte) が多く、3 位以上の回答と明確にアルゴリズムの差があるのでここから解説をスタートしようと思う。
</p>
<div class="codeblock">
- <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#E36209">s</span><span style="color:#D73A49">=</span><span style="color:#005CC5">gets</span></span>
-<span class="line"><span style="color:#005CC5">?A</span><span style="color:#24292E">.</span><span style="color:#6F42C1">upto</span><span style="color:#24292E">(</span><span style="color:#005CC5">?Z</span><span style="color:#24292E">){(b,),m</span><span style="color:#D73A49">=</span><span style="color:#24292E">s.</span><span style="color:#6F42C1">scan</span><span style="color:#24292E">(</span><span style="color:#032F62">/(?=(.</span><span style="color:#22863A;font-weight:bold">\B</span><span style="color:#032F62">.))/</span><span style="color:#24292E">).</span><span style="color:#6F42C1">tally</span><span style="color:#24292E">.</span><span style="color:#6F42C1">max_by</span><span style="color:#24292E">{</span><span style="color:#005CC5">_2</span><span style="color:#24292E">}</span></span>
-<span class="line"><span style="color:#24292E">m</span><span style="color:#D73A49">></span><span style="color:#005CC5">1</span><span style="color:#D73A49">&#x26;&#x26;</span><span style="color:#24292E">(s.</span><span style="color:#6F42C1">gsub!b</span><span style="color:#24292E">,it;$*</span><span style="color:#D73A49">&#x3C;&#x3C;</span><span style="color:#24292E">it</span><span style="color:#D73A49">+</span><span style="color:#005CC5">?:</span><span style="color:#D73A49">+</span><span style="color:#24292E">b)}</span></span>
-<span class="line"><span style="color:#005CC5">puts</span><span style="color:#24292E">$*</span><span style="color:#D73A49">*</span><span style="color:#005CC5">?,</span><span style="color:#24292E">,s</span></span></code></pre>
+ <pre class="highlight" style="background-color:#f5f5f5"><code><span style="color: #24292f;background-color: #f6f8fa">s</span><span style="color: #0550ae">=</span><span style="color: #953800">gets</span>
+<span style="color: #0a3069">?A</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">upto</span><span style="color: #24292f;background-color: #f6f8fa">(</span><span style="color: #0a3069">?Z</span><span style="color: #24292f;background-color: #f6f8fa">){(</span><span style="color: #24292f;background-color: #f6f8fa">b</span><span style="color: #24292f;background-color: #f6f8fa">,),</span><span style="color: #24292f;background-color: #f6f8fa">m</span><span style="color: #0550ae">=</span><span style="color: #24292f;background-color: #f6f8fa">s</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">scan</span><span style="color: #24292f;background-color: #f6f8fa">(</span><span style="color: #116329">/(?=(.\B.))/</span><span style="color: #24292f;background-color: #f6f8fa">).</span><span style="color: #8250df">tally</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">max_by</span><span style="color: #24292f;background-color: #f6f8fa">{</span><span style="color: #24292f;background-color: #f6f8fa">_2</span><span style="color: #24292f;background-color: #f6f8fa">}</span>
+<span style="color: #24292f;background-color: #f6f8fa">m</span><span style="color: #0550ae">&gt;</span><span style="color: #0550ae">1</span><span style="color: #0550ae">&amp;&amp;</span><span style="color: #24292f;background-color: #f6f8fa">(</span><span style="color: #24292f;background-color: #f6f8fa">s</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">gsub!</span><span style="color: #24292f;background-color: #f6f8fa">b</span><span style="color: #24292f;background-color: #f6f8fa">,</span><span style="color: #24292f;background-color: #f6f8fa">it</span><span style="color: #24292f;background-color: #f6f8fa">;</span><span style="color: #0550ae">$*</span><span style="color: #0550ae">&lt;&lt;</span><span style="color: #953800">it</span><span style="color: #0550ae">+</span><span style="color: #0a3069">?:</span><span style="color: #0550ae">+</span><span style="color: #24292f;background-color: #f6f8fa">b</span><span style="color: #24292f;background-color: #f6f8fa">)}</span><span style="color: #0a3069">
+puts$**?,,s</span>
+</code></pre>
</div>
<p>
変数名などの細かい差異を除けば他の 107 byte 回答と同じだが、 <code>String#scan</code> に渡す正規表現にこれを採用していたのは私だけだったのではないだろうか。 <code>/(?=(\S\S))/</code> や <code>/(?=(\w\w))/</code> と比べて短くはならないので意味はない。
@@ -168,9 +170,10 @@
<code>Enumerable#max_by</code> で最頻値を取ってきた後は、多重代入を使って必要な値を取り出している。
</p>
<div class="codeblock">
- <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#E36209">x</span><span style="color:#D73A49"> =</span><span style="color:#24292E"> [[</span><span style="color:#032F62">"la"</span><span style="color:#24292E">], </span><span style="color:#005CC5">3</span><span style="color:#24292E">]</span></span>
-<span class="line"><span style="color:#24292E">(b,),m </span><span style="color:#D73A49">=</span><span style="color:#24292E"> x</span></span>
-<span class="line"><span style="color:#6A737D"># => b = "la", m = 3</span></span></code></pre>
+ <pre class="highlight" style="background-color:#f5f5f5"><code><span style="color: #24292f;background-color: #f6f8fa">x</span> <span style="color: #0550ae">=</span> <span style="color: #24292f;background-color: #f6f8fa">[[</span><span style="color: #0a3069">"la"</span><span style="color: #24292f;background-color: #f6f8fa">],</span> <span style="color: #0550ae">3</span><span style="color: #24292f;background-color: #f6f8fa">]</span>
+<span style="color: #24292f;background-color: #f6f8fa">(</span><span style="color: #24292f;background-color: #f6f8fa">b</span><span style="color: #24292f;background-color: #f6f8fa">,),</span><span style="color: #24292f;background-color: #f6f8fa">m</span> <span style="color: #0550ae">=</span> <span style="color: #24292f;background-color: #f6f8fa">x</span>
+<span style="color: #6e7781"># =&gt; b = "la", m = 3</span>
+</code></pre>
</div>
<p>
置換テーブルのデータは <code>$*</code> へと追加しているが、これは Ruby の特殊変数で、本来は <code>Object::ARGV</code> を指す。ここでは単に最初から空配列で初期化されている便利な入れ物として用いている。
@@ -185,10 +188,11 @@
回答 A をぐっと睨むと、<code>m&gt;1&amp;&amp;(...)</code> の括弧を削りたくなる。しかしそれには <code>m&gt;1&amp;&amp;</code> がどうしても邪魔になる。というわけで終了条件を工夫することでなんとか <code>m</code> を排除できないかを考えた。それがこちら。
</p>
<div class="codeblock">
- <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#E36209">s</span><span style="color:#D73A49">=</span><span style="color:#005CC5">gets</span></span>
-<span class="line"><span style="color:#005CC5">?A</span><span style="color:#24292E">.</span><span style="color:#6F42C1">upto</span><span style="color:#24292E">(</span><span style="color:#005CC5">?Z</span><span style="color:#24292E">){(b,),</span><span style="color:#D73A49">=</span><span style="color:#24292E">(</span><span style="color:#005CC5">?_</span><span style="color:#D73A49">+</span><span style="color:#24292E">s).</span><span style="color:#6F42C1">scan</span><span style="color:#24292E">(</span><span style="color:#032F62">/(?=(.</span><span style="color:#22863A;font-weight:bold">\B</span><span style="color:#032F62">.))/</span><span style="color:#24292E">).</span><span style="color:#6F42C1">tally</span><span style="color:#24292E">.</span><span style="color:#6F42C1">max_by</span><span style="color:#24292E">{</span><span style="color:#005CC5">_2</span><span style="color:#24292E">}</span></span>
-<span class="line"><span style="color:#24292E">$*</span><span style="color:#D73A49">&#x3C;&#x3C;</span><span style="color:#24292E">it</span><span style="color:#D73A49">+</span><span style="color:#005CC5">?:</span><span style="color:#D73A49">+</span><span style="color:#24292E">b </span><span style="color:#D73A49">if</span><span style="color:#24292E"> s.</span><span style="color:#6F42C1">gsub!b</span><span style="color:#24292E">,it}</span></span>
-<span class="line"><span style="color:#005CC5">puts</span><span style="color:#24292E">$*</span><span style="color:#D73A49">*</span><span style="color:#005CC5">?,</span><span style="color:#24292E">,s</span></span></code></pre>
+ <pre class="highlight" style="background-color:#f5f5f5"><code><span style="color: #24292f;background-color: #f6f8fa">s</span><span style="color: #0550ae">=</span><span style="color: #953800">gets</span>
+<span style="color: #0a3069">?A</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">upto</span><span style="color: #24292f;background-color: #f6f8fa">(</span><span style="color: #0a3069">?Z</span><span style="color: #24292f;background-color: #f6f8fa">){(</span><span style="color: #24292f;background-color: #f6f8fa">b</span><span style="color: #24292f;background-color: #f6f8fa">,),</span><span style="color: #0550ae">=</span><span style="color: #24292f;background-color: #f6f8fa">(</span><span style="color: #0a3069">?_</span><span style="color: #0550ae">+</span><span style="color: #24292f;background-color: #f6f8fa">s</span><span style="color: #24292f;background-color: #f6f8fa">).</span><span style="color: #8250df">scan</span><span style="color: #24292f;background-color: #f6f8fa">(</span><span style="color: #116329">/(?=(.\B.))/</span><span style="color: #24292f;background-color: #f6f8fa">).</span><span style="color: #8250df">tally</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">max_by</span><span style="color: #24292f;background-color: #f6f8fa">{</span><span style="color: #24292f;background-color: #f6f8fa">_2</span><span style="color: #24292f;background-color: #f6f8fa">}</span>
+<span style="color: #0550ae">$*</span><span style="color: #0550ae">&lt;&lt;</span><span style="color: #953800">it</span><span style="color: #0550ae">+</span><span style="color: #0a3069">?:</span><span style="color: #0550ae">+</span><span style="color: #24292f;background-color: #f6f8fa">b</span> <span style="color: #cf222e">if</span> <span style="color: #24292f;background-color: #f6f8fa">s</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">gsub!</span><span style="color: #24292f;background-color: #f6f8fa">b</span><span style="color: #24292f;background-color: #f6f8fa">,</span><span style="color: #24292f;background-color: #f6f8fa">it</span><span style="color: #24292f;background-color: #f6f8fa">}</span><span style="color: #0a3069">
+puts$**?,,s</span>
+</code></pre>
</div>
<p>
<code>s</code> の先頭に番兵 <code>_</code> を置くことで、bi-gram の出現頻度がすべて 1 になったとき、<code>b</code> へと代入される値が「<code>_</code> + (<code>s</code> の先頭の文字)」になる。これを <code>String#gsub!</code> で置き換えようとすると、そのような文字列は <code>s</code> 中にないので置換が発生しない。<code>String#gsub!</code> は置換が起きなかったとき <code>nil</code> を返すので、これを使って条件分岐ができる。<code>&amp;&amp;</code> だと優先度の関係から <code>String#gsub!</code> の括弧が省略できないが、後置 if なら省略できる。
@@ -203,10 +207,11 @@
<code>Kernel#gets</code> は、入力を特殊変数 <code>$_</code> へ代入する。これは Perl 由来の挙動で、Ruby にはいくつか <code>$_</code> を参照するものがある。これを使って変数 <code>s</code> を置き換えると次のようになる。
</p>
<div class="codeblock">
- <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#005CC5">gets</span></span>
-<span class="line"><span style="color:#005CC5">?A</span><span style="color:#24292E">.</span><span style="color:#6F42C1">upto</span><span style="color:#24292E">(</span><span style="color:#005CC5">?Z</span><span style="color:#24292E">){(b,),</span><span style="color:#D73A49">=</span><span style="color:#032F62">"_</span><span style="color:#24292E">#$_</span><span style="color:#032F62">"</span><span style="color:#24292E">.</span><span style="color:#6F42C1">scan</span><span style="color:#24292E">(</span><span style="color:#032F62">/(?=(.</span><span style="color:#22863A;font-weight:bold">\B</span><span style="color:#032F62">.))/</span><span style="color:#24292E">).</span><span style="color:#6F42C1">tally</span><span style="color:#24292E">.</span><span style="color:#6F42C1">max_by</span><span style="color:#24292E">{</span><span style="color:#005CC5">_2</span><span style="color:#24292E">}</span></span>
-<span class="line"><span style="color:#24292E">$*</span><span style="color:#D73A49">&#x3C;&#x3C;</span><span style="color:#24292E">it</span><span style="color:#D73A49">+</span><span style="color:#005CC5">?:</span><span style="color:#D73A49">+</span><span style="color:#24292E">b </span><span style="color:#D73A49">if</span><span style="color:#24292E">$_.</span><span style="color:#6F42C1">gsub!b</span><span style="color:#24292E">,it}</span></span>
-<span class="line"><span style="color:#005CC5">puts</span><span style="color:#24292E">$*</span><span style="color:#D73A49">*</span><span style="color:#005CC5">?,</span><span style="color:#24292E">,$_</span></span></code></pre>
+ <pre class="highlight" style="background-color:#f5f5f5"><code><span style="color: #953800">gets</span>
+<span style="color: #0a3069">?A</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">upto</span><span style="color: #24292f;background-color: #f6f8fa">(</span><span style="color: #0a3069">?Z</span><span style="color: #24292f;background-color: #f6f8fa">){(</span><span style="color: #24292f;background-color: #f6f8fa">b</span><span style="color: #24292f;background-color: #f6f8fa">,),</span><span style="color: #0550ae">=</span><span style="color: #0a3069">"_</span><span style="color: #24292f">#$_</span><span style="color: #0a3069">"</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">scan</span><span style="color: #24292f;background-color: #f6f8fa">(</span><span style="color: #116329">/(?=(.\B.))/</span><span style="color: #24292f;background-color: #f6f8fa">).</span><span style="color: #8250df">tally</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">max_by</span><span style="color: #24292f;background-color: #f6f8fa">{</span><span style="color: #24292f;background-color: #f6f8fa">_2</span><span style="color: #24292f;background-color: #f6f8fa">}</span>
+<span style="color: #0550ae">$*</span><span style="color: #0550ae">&lt;&lt;</span><span style="color: #953800">it</span><span style="color: #0550ae">+</span><span style="color: #0a3069">?:</span><span style="color: #0550ae">+</span><span style="color: #24292f;background-color: #f6f8fa">b</span> <span style="color: #cf222e">if</span><span style="color: #0550ae">$_</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">gsub!</span><span style="color: #24292f;background-color: #f6f8fa">b</span><span style="color: #24292f;background-color: #f6f8fa">,</span><span style="color: #24292f;background-color: #f6f8fa">it</span><span style="color: #24292f;background-color: #f6f8fa">}</span><span style="color: #0a3069">
+puts$**?,,$_</span>
+</code></pre>
</div>
<p>
これで 1 byte 縮む。
@@ -218,9 +223,10 @@
回答 C を眺めると、<code>b</code> への代入に文字を費やしすぎている。これを <code>String#gsub!</code> の第一引数に直接書いてはどうか。更に、直前のマッチしたパターンを指す特殊変数 <code>$&amp;</code> を使えば、変数 <code>b</code> を排除できる。それがこちら。
</p>
<div class="codeblock">
- <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#005CC5">gets</span></span>
-<span class="line"><span style="color:#005CC5">?A</span><span style="color:#24292E">.</span><span style="color:#6F42C1">upto</span><span style="color:#24292E">(</span><span style="color:#005CC5">?Z</span><span style="color:#24292E">){$*</span><span style="color:#D73A49">&#x3C;&#x3C;</span><span style="color:#24292E">it</span><span style="color:#D73A49">+</span><span style="color:#005CC5">?:</span><span style="color:#D73A49">+</span><span style="color:#24292E">$&#x26;</span><span style="color:#D73A49">if</span><span style="color:#24292E">$_.</span><span style="color:#6F42C1">gsub!</span><span style="color:#032F62">"_</span><span style="color:#24292E">#$_</span><span style="color:#032F62">"</span><span style="color:#24292E">.</span><span style="color:#6F42C1">scan</span><span style="color:#24292E">(</span><span style="color:#032F62">/(?=(.</span><span style="color:#22863A;font-weight:bold">\B</span><span style="color:#032F62">.))/</span><span style="color:#24292E">).</span><span style="color:#6F42C1">tally</span><span style="color:#24292E">.</span><span style="color:#6F42C1">max_by</span><span style="color:#24292E">{</span><span style="color:#005CC5">_2</span><span style="color:#24292E">}[</span><span style="color:#005CC5">0</span><span style="color:#24292E">][</span><span style="color:#005CC5">0</span><span style="color:#24292E">],it}</span></span>
-<span class="line"><span style="color:#005CC5">puts</span><span style="color:#24292E">$*</span><span style="color:#D73A49">*</span><span style="color:#005CC5">?,</span><span style="color:#24292E">,$_</span></span></code></pre>
+ <pre class="highlight" style="background-color:#f5f5f5"><code><span style="color: #953800">gets</span>
+<span style="color: #0a3069">?A</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">upto</span><span style="color: #24292f;background-color: #f6f8fa">(</span><span style="color: #0a3069">?Z</span><span style="color: #24292f;background-color: #f6f8fa">){</span><span style="color: #0550ae">$*</span><span style="color: #0550ae">&lt;&lt;</span><span style="color: #953800">it</span><span style="color: #0550ae">+</span><span style="color: #0a3069">?:</span><span style="color: #0550ae">+</span><span style="color: #0550ae">$&amp;</span><span style="color: #cf222e">if</span><span style="color: #0550ae">$_</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">gsub!</span><span style="color: #0a3069">"_</span><span style="color: #24292f">#$_</span><span style="color: #0a3069">"</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">scan</span><span style="color: #24292f;background-color: #f6f8fa">(</span><span style="color: #116329">/(?=(.\B.))/</span><span style="color: #24292f;background-color: #f6f8fa">).</span><span style="color: #8250df">tally</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">max_by</span><span style="color: #24292f;background-color: #f6f8fa">{</span><span style="color: #24292f;background-color: #f6f8fa">_2</span><span style="color: #24292f;background-color: #f6f8fa">}[</span><span style="color: #0550ae">0</span><span style="color: #24292f;background-color: #f6f8fa">][</span><span style="color: #0550ae">0</span><span style="color: #24292f;background-color: #f6f8fa">],</span><span style="color: #24292f;background-color: #f6f8fa">it</span><span style="color: #24292f;background-color: #f6f8fa">}</span><span style="color: #0a3069">
+puts$**?,,$_</span>
+</code></pre>
</div>
<p>
これにより 2 bytes も一気に縮まった。
@@ -232,9 +238,10 @@
回答 D を提出したことで tompng 氏のスコアを越え、氏のコードを閲覧できるようになった。そこから少し変更したものが、mame 氏と (変数名などの些事を除いて) 同じ以下のコードである。
</p>
<div class="codeblock">
- <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#E36209">s</span><span style="color:#D73A49">=</span><span style="color:#005CC5">gets</span></span>
-<span class="line"><span style="color:#005CC5">?A</span><span style="color:#24292E">.</span><span style="color:#6F42C1">upto</span><span style="color:#24292E">(</span><span style="color:#005CC5">?Z</span><span style="color:#24292E">){s.</span><span style="color:#6F42C1">scan</span><span style="color:#24292E">(</span><span style="color:#032F62">/(?=(.</span><span style="color:#22863A;font-weight:bold">\B</span><span style="color:#032F62">.))/</span><span style="color:#24292E">).</span><span style="color:#6F42C1">tally</span><span style="color:#24292E">.</span><span style="color:#6F42C1">max_by</span><span style="color:#24292E">{</span><span style="color:#005CC5">_2</span><span style="color:#24292E">}</span><span style="color:#D73A49">in</span><span style="color:#24292E">[b],1</span><span style="color:#6F42C1">or</span><span style="color:#24292E">($*</span><span style="color:#D73A49">&#x3C;&#x3C;</span><span style="color:#24292E">it</span><span style="color:#D73A49">+</span><span style="color:#005CC5">?:</span><span style="color:#D73A49">+</span><span style="color:#24292E">b;s.</span><span style="color:#6F42C1">gsub!b</span><span style="color:#24292E">,it)}</span></span>
-<span class="line"><span style="color:#005CC5">puts</span><span style="color:#24292E">$*</span><span style="color:#D73A49">*</span><span style="color:#005CC5">?,</span><span style="color:#24292E">,s</span></span></code></pre>
+ <pre class="highlight" style="background-color:#f5f5f5"><code><span style="color: #24292f;background-color: #f6f8fa">s</span><span style="color: #0550ae">=</span><span style="color: #953800">gets</span>
+<span style="color: #0a3069">?A</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">upto</span><span style="color: #24292f;background-color: #f6f8fa">(</span><span style="color: #0a3069">?Z</span><span style="color: #24292f;background-color: #f6f8fa">){</span><span style="color: #24292f;background-color: #f6f8fa">s</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">scan</span><span style="color: #24292f;background-color: #f6f8fa">(</span><span style="color: #116329">/(?=(.\B.))/</span><span style="color: #24292f;background-color: #f6f8fa">).</span><span style="color: #8250df">tally</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">max_by</span><span style="color: #24292f;background-color: #f6f8fa">{</span><span style="color: #24292f;background-color: #f6f8fa">_2</span><span style="color: #24292f;background-color: #f6f8fa">}</span><span style="color: #cf222e">in</span><span style="color: #24292f;background-color: #f6f8fa">[</span><span style="color: #24292f;background-color: #f6f8fa">b</span><span style="color: #24292f;background-color: #f6f8fa">],</span><span style="color: #0550ae">1</span><span style="color: #0550ae">or</span><span style="color: #24292f;background-color: #f6f8fa">(</span><span style="color: #0550ae">$*</span><span style="color: #0550ae">&lt;&lt;</span><span style="color: #953800">it</span><span style="color: #0550ae">+</span><span style="color: #0a3069">?:</span><span style="color: #0550ae">+</span><span style="color: #24292f;background-color: #f6f8fa">b</span><span style="color: #24292f;background-color: #f6f8fa">;</span><span style="color: #24292f;background-color: #f6f8fa">s</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">gsub!</span><span style="color: #24292f;background-color: #f6f8fa">b</span><span style="color: #24292f;background-color: #f6f8fa">,</span><span style="color: #24292f;background-color: #f6f8fa">it</span><span style="color: #24292f;background-color: #f6f8fa">)}</span><span style="color: #0a3069">
+puts$**?,,s</span>
+</code></pre>
</div>
<p>
ここまでとは大きく異なる戦略で終了条件を判定している。使われているのはパターンマッチで、<code>in</code> がマッチの有無を <code>true</code> / <code>false</code> で返すことを利用している。<code>or</code> を用いて、最頻値の出現回数が 1 でないなら置換処理を継続する。
@@ -243,10 +250,11 @@
パターンマッチの利用については途中何度か検討したが、1 でないときに処理を実行するという方針で実装しようとしてしまい、上手く短縮できなかった。
</p>
<div class="codeblock">
- <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D"># これは 106 byte</span></span>
-<span class="line"><span style="color:#E36209">s</span><span style="color:#D73A49">=</span><span style="color:#005CC5">gets</span></span>
-<span class="line"><span style="color:#005CC5">?A</span><span style="color:#24292E">.</span><span style="color:#6F42C1">upto</span><span style="color:#24292E">(</span><span style="color:#005CC5">?Z</span><span style="color:#24292E">){s.</span><span style="color:#6F42C1">scan</span><span style="color:#24292E">(</span><span style="color:#032F62">/(?=(.</span><span style="color:#22863A;font-weight:bold">\B</span><span style="color:#032F62">.))/</span><span style="color:#24292E">).</span><span style="color:#6F42C1">tally</span><span style="color:#24292E">.</span><span style="color:#6F42C1">max_by</span><span style="color:#24292E">{</span><span style="color:#005CC5">_2</span><span style="color:#24292E">}</span><span style="color:#D73A49">in</span><span style="color:#24292E">[b],</span><span style="color:#005CC5">2</span><span style="color:#24292E">..</span><span style="color:#6F42C1">and</span><span style="color:#24292E">($*</span><span style="color:#D73A49">&#x3C;&#x3C;</span><span style="color:#24292E">it</span><span style="color:#D73A49">+</span><span style="color:#005CC5">?:</span><span style="color:#D73A49">+</span><span style="color:#24292E">b;s.</span><span style="color:#6F42C1">gsub!b</span><span style="color:#24292E">,it)}</span></span>
-<span class="line"><span style="color:#005CC5">puts</span><span style="color:#24292E">$*</span><span style="color:#D73A49">*</span><span style="color:#005CC5">?,</span><span style="color:#24292E">,s</span></span></code></pre>
+ <pre class="highlight" style="background-color:#f5f5f5"><code><span style="color: #6e7781"># これは 106 byte</span>
+<span style="color: #24292f;background-color: #f6f8fa">s</span><span style="color: #0550ae">=</span><span style="color: #953800">gets</span>
+<span style="color: #0a3069">?A</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">upto</span><span style="color: #24292f;background-color: #f6f8fa">(</span><span style="color: #0a3069">?Z</span><span style="color: #24292f;background-color: #f6f8fa">){</span><span style="color: #24292f;background-color: #f6f8fa">s</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">scan</span><span style="color: #24292f;background-color: #f6f8fa">(</span><span style="color: #116329">/(?=(.\B.))/</span><span style="color: #24292f;background-color: #f6f8fa">).</span><span style="color: #8250df">tally</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">max_by</span><span style="color: #24292f;background-color: #f6f8fa">{</span><span style="color: #24292f;background-color: #f6f8fa">_2</span><span style="color: #24292f;background-color: #f6f8fa">}</span><span style="color: #cf222e">in</span><span style="color: #24292f;background-color: #f6f8fa">[</span><span style="color: #24292f;background-color: #f6f8fa">b</span><span style="color: #24292f;background-color: #f6f8fa">],</span><span style="color: #0550ae">2</span><span style="color: #0550ae">..</span><span style="color: #0550ae">and</span><span style="color: #24292f;background-color: #f6f8fa">(</span><span style="color: #0550ae">$*</span><span style="color: #0550ae">&lt;&lt;</span><span style="color: #953800">it</span><span style="color: #0550ae">+</span><span style="color: #0a3069">?:</span><span style="color: #0550ae">+</span><span style="color: #24292f;background-color: #f6f8fa">b</span><span style="color: #24292f;background-color: #f6f8fa">;</span><span style="color: #24292f;background-color: #f6f8fa">s</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">gsub!</span><span style="color: #24292f;background-color: #f6f8fa">b</span><span style="color: #24292f;background-color: #f6f8fa">,</span><span style="color: #24292f;background-color: #f6f8fa">it</span><span style="color: #24292f;background-color: #f6f8fa">)}</span><span style="color: #0a3069">
+puts$**?,,s</span>
+</code></pre>
</div>
</section>
<section id="section--hole-2--answer-f">
@@ -266,10 +274,11 @@
<code>ruby</code> で <code>-p</code> を付けると、以下のようなコードを書いたかのように動作する。
</p>
<div class="codeblock">
- <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#D73A49">while</span><span style="color:#005CC5"> gets</span></span>
-<span class="line"><span style="color:#24292E"> ... </span><span style="color:#6A737D"># 記載したコードの処理</span></span>
-<span class="line"><span style="color:#005CC5"> puts</span><span style="color:#24292E"> $_</span></span>
-<span class="line"><span style="color:#D73A49">end</span></span></code></pre>
+ <pre class="highlight" style="background-color:#f5f5f5"><code><span style="color: #cf222e">while</span> <span style="color: #953800">gets</span>
+ <span style="color: #0550ae">...</span> <span style="color: #6e7781"># 記載したコードの処理</span>
+ <span style="color: #953800">puts</span> <span style="color: #0550ae">$_</span>
+<span style="color: #cf222e">end</span>
+</code></pre>
</div>
<p>
また、<code>Kernel#gsub</code> という <code>$_ = $_.gsub(...)</code> と同様の処理をおこなうメソッドが生えてくる。今回は <code>String#gsub!</code> も使うので、shebang の分を回収できれば短縮になりそうだ。
@@ -278,18 +287,20 @@
というわけで、実はこれまでも shebang での短縮は何度か試していた。しかし、いずれも 1 byte 増えたり変化しなかったりで成果を上げられずにいた。回答 E についても同様に、以下のようなコードを作っていた。
</p>
<div class="codeblock">
- <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D">#!ruby -p</span></span>
-<span class="line"><span style="color:#005CC5">?A</span><span style="color:#24292E">.</span><span style="color:#6F42C1">upto</span><span style="color:#24292E">(</span><span style="color:#005CC5">?Z</span><span style="color:#24292E">){$_.</span><span style="color:#6F42C1">scan</span><span style="color:#24292E">(</span><span style="color:#032F62">/(?=(.</span><span style="color:#22863A;font-weight:bold">\B</span><span style="color:#032F62">.))/</span><span style="color:#24292E">).</span><span style="color:#6F42C1">tally</span><span style="color:#24292E">.</span><span style="color:#6F42C1">max_by</span><span style="color:#24292E">{</span><span style="color:#005CC5">_2</span><span style="color:#24292E">}</span><span style="color:#D73A49">in</span><span style="color:#24292E">[b],1</span><span style="color:#6F42C1">or</span><span style="color:#24292E">($*</span><span style="color:#D73A49">&#x3C;&#x3C;</span><span style="color:#24292E">it</span><span style="color:#D73A49">+</span><span style="color:#005CC5">?:</span><span style="color:#D73A49">+</span><span style="color:#24292E">b;</span><span style="color:#005CC5">gsub</span><span style="color:#24292E"> b,it)}</span></span>
-<span class="line"><span style="color:#005CC5">puts</span><span style="color:#24292E">$*</span><span style="color:#D73A49">*</span><span style="color:#005CC5">?,</span></span></code></pre>
+ <pre class="highlight" style="background-color:#f5f5f5"><code><span style="color: #6e7781">#!ruby -p</span>
+<span style="color: #0a3069">?A</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">upto</span><span style="color: #24292f;background-color: #f6f8fa">(</span><span style="color: #0a3069">?Z</span><span style="color: #24292f;background-color: #f6f8fa">){</span><span style="color: #0550ae">$_</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">scan</span><span style="color: #24292f;background-color: #f6f8fa">(</span><span style="color: #116329">/(?=(.\B.))/</span><span style="color: #24292f;background-color: #f6f8fa">).</span><span style="color: #8250df">tally</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">max_by</span><span style="color: #24292f;background-color: #f6f8fa">{</span><span style="color: #24292f;background-color: #f6f8fa">_2</span><span style="color: #24292f;background-color: #f6f8fa">}</span><span style="color: #cf222e">in</span><span style="color: #24292f;background-color: #f6f8fa">[</span><span style="color: #24292f;background-color: #f6f8fa">b</span><span style="color: #24292f;background-color: #f6f8fa">],</span><span style="color: #0550ae">1</span><span style="color: #0550ae">or</span><span style="color: #24292f;background-color: #f6f8fa">(</span><span style="color: #0550ae">$*</span><span style="color: #0550ae">&lt;&lt;</span><span style="color: #953800">it</span><span style="color: #0550ae">+</span><span style="color: #0a3069">?:</span><span style="color: #0550ae">+</span><span style="color: #24292f;background-color: #f6f8fa">b</span><span style="color: #24292f;background-color: #f6f8fa">;</span><span style="color: #953800">gsub</span> <span style="color: #24292f;background-color: #f6f8fa">b</span><span style="color: #24292f;background-color: #f6f8fa">,</span><span style="color: #24292f;background-color: #f6f8fa">it</span><span style="color: #24292f;background-color: #f6f8fa">)}</span><span style="color: #0a3069">
+puts$**?,</span>
+</code></pre>
</div>
<p>
しかしこれは 103 byte で縮められない。にっくきは <code>gsub</code> と <code>b</code> の間のスペースである。せっかく <code>s.gsub!</code> を <code>gsub</code> にしたのに、後ろが記号でなくなったことでスペースが生じている。といって、括弧を付けるのも上手くはいかない。
</p>
<div class="codeblock">
- <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D"># これも同じく 103 byte</span></span>
-<span class="line"><span style="color:#6A737D">#!ruby -p</span></span>
-<span class="line"><span style="color:#005CC5">?A</span><span style="color:#24292E">.</span><span style="color:#6F42C1">upto</span><span style="color:#24292E">(</span><span style="color:#005CC5">?Z</span><span style="color:#24292E">){$_.</span><span style="color:#6F42C1">scan</span><span style="color:#24292E">(</span><span style="color:#032F62">/(?=(.</span><span style="color:#22863A;font-weight:bold">\B</span><span style="color:#032F62">.))/</span><span style="color:#24292E">).</span><span style="color:#6F42C1">tally</span><span style="color:#24292E">.</span><span style="color:#6F42C1">max_by</span><span style="color:#24292E">{</span><span style="color:#005CC5">_2</span><span style="color:#24292E">}</span><span style="color:#D73A49">in</span><span style="color:#24292E">[b],1or$*</span><span style="color:#D73A49">&#x3C;&#x3C;</span><span style="color:#24292E">it</span><span style="color:#D73A49">+</span><span style="color:#005CC5">?:</span><span style="color:#D73A49">+</span><span style="color:#24292E">b</span><span style="color:#D73A49">&#x26;&#x26;</span><span style="color:#005CC5">gsub</span><span style="color:#24292E">(b,it)}</span></span>
-<span class="line"><span style="color:#005CC5">puts</span><span style="color:#24292E">$*</span><span style="color:#D73A49">*</span><span style="color:#005CC5">?,</span></span></code></pre>
+ <pre class="highlight" style="background-color:#f5f5f5"><code><span style="color: #6e7781"># これも同じく 103 byte</span>
+<span style="color: #6e7781">#!ruby -p</span>
+<span style="color: #0a3069">?A</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">upto</span><span style="color: #24292f;background-color: #f6f8fa">(</span><span style="color: #0a3069">?Z</span><span style="color: #24292f;background-color: #f6f8fa">){</span><span style="color: #0550ae">$_</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">scan</span><span style="color: #24292f;background-color: #f6f8fa">(</span><span style="color: #116329">/(?=(.\B.))/</span><span style="color: #24292f;background-color: #f6f8fa">).</span><span style="color: #8250df">tally</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">max_by</span><span style="color: #24292f;background-color: #f6f8fa">{</span><span style="color: #24292f;background-color: #f6f8fa">_2</span><span style="color: #24292f;background-color: #f6f8fa">}</span><span style="color: #cf222e">in</span><span style="color: #24292f;background-color: #f6f8fa">[</span><span style="color: #24292f;background-color: #f6f8fa">b</span><span style="color: #24292f;background-color: #f6f8fa">],</span><span style="color: #0550ae">1</span><span style="color: #0550ae">or</span><span style="color: #0550ae">$*</span><span style="color: #0550ae">&lt;&lt;</span><span style="color: #953800">it</span><span style="color: #0550ae">+</span><span style="color: #0a3069">?:</span><span style="color: #0550ae">+</span><span style="color: #24292f;background-color: #f6f8fa">b</span><span style="color: #0550ae">&amp;&amp;</span><span style="color: #953800">gsub</span><span style="color: #24292f;background-color: #f6f8fa">(</span><span style="color: #24292f;background-color: #f6f8fa">b</span><span style="color: #24292f;background-color: #f6f8fa">,</span><span style="color: #24292f;background-color: #f6f8fa">it</span><span style="color: #24292f;background-color: #f6f8fa">)}</span><span style="color: #0a3069">
+puts$**?,</span>
+</code></pre>
</div>
<p>
外側の括弧を移動させてくれば <code>gsub</code> と <code>b</code> の間のスペースを消せるが、<code>;</code> を <code>&amp;&amp;</code> にせねばならず失敗する。この問題を解決したのが最終回答の 102 byte コードである。
@@ -298,9 +309,10 @@
<section id="section--hole-2--answer-g">
<h3><a href="#section--hole-2--answer-g">最終回答 (102 byte)</a></h3>
<div class="codeblock">
- <pre class="shiki github-light" style="background-color:#f5f5f5;color:#24292e" tabindex="0"><code><span class="line"><span style="color:#6A737D">#!ruby -p</span></span>
-<span class="line"><span style="color:#005CC5">?A</span><span style="color:#24292E">.</span><span style="color:#6F42C1">upto</span><span style="color:#24292E">(</span><span style="color:#005CC5">?Z</span><span style="color:#24292E">){$_.</span><span style="color:#6F42C1">scan</span><span style="color:#24292E">(</span><span style="color:#032F62">/(?=(.</span><span style="color:#22863A;font-weight:bold">\B</span><span style="color:#032F62">.))/</span><span style="color:#24292E">).</span><span style="color:#6F42C1">tally</span><span style="color:#24292E">.</span><span style="color:#6F42C1">max_by</span><span style="color:#24292E">{</span><span style="color:#005CC5">_2</span><span style="color:#24292E">}</span><span style="color:#D73A49">in</span><span style="color:#24292E">[b],1or$*</span><span style="color:#D73A49">&#x3C;&#x3C;</span><span style="color:#24292E">it</span><span style="color:#D73A49">+</span><span style="color:#005CC5">?:</span><span style="color:#D73A49">+</span><span style="color:#24292E">b</span><span style="color:#D73A49">%</span><span style="color:#005CC5">gsub</span><span style="color:#24292E">(b,it)}</span></span>
-<span class="line"><span style="color:#005CC5">puts</span><span style="color:#24292E">$*</span><span style="color:#D73A49">*</span><span style="color:#005CC5">?,</span></span></code></pre>
+ <pre class="highlight" style="background-color:#f5f5f5"><code><span style="color: #6e7781">#!ruby -p</span>
+<span style="color: #0a3069">?A</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">upto</span><span style="color: #24292f;background-color: #f6f8fa">(</span><span style="color: #0a3069">?Z</span><span style="color: #24292f;background-color: #f6f8fa">){</span><span style="color: #0550ae">$_</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">scan</span><span style="color: #24292f;background-color: #f6f8fa">(</span><span style="color: #116329">/(?=(.\B.))/</span><span style="color: #24292f;background-color: #f6f8fa">).</span><span style="color: #8250df">tally</span><span style="color: #24292f;background-color: #f6f8fa">.</span><span style="color: #8250df">max_by</span><span style="color: #24292f;background-color: #f6f8fa">{</span><span style="color: #24292f;background-color: #f6f8fa">_2</span><span style="color: #24292f;background-color: #f6f8fa">}</span><span style="color: #cf222e">in</span><span style="color: #24292f;background-color: #f6f8fa">[</span><span style="color: #24292f;background-color: #f6f8fa">b</span><span style="color: #24292f;background-color: #f6f8fa">],</span><span style="color: #0550ae">1</span><span style="color: #0550ae">or</span><span style="color: #0550ae">$*</span><span style="color: #0550ae">&lt;&lt;</span><span style="color: #953800">it</span><span style="color: #0550ae">+</span><span style="color: #0a3069">?:</span><span style="color: #0550ae">+</span><span style="color: #24292f;background-color: #f6f8fa">b</span><span style="color: #0550ae">%</span><span style="color: #953800">gsub</span><span style="color: #24292f;background-color: #f6f8fa">(</span><span style="color: #24292f;background-color: #f6f8fa">b</span><span style="color: #24292f;background-color: #f6f8fa">,</span><span style="color: #24292f;background-color: #f6f8fa">it</span><span style="color: #24292f;background-color: #f6f8fa">)}</span><span style="color: #0a3069">
+puts$**?,</span>
+</code></pre>
</div>
<p>
<code>String#%</code> は文字列のフォーマット処理をおこなう演算子だが、ここでは特にフォーマット目的で呼んでいるわけではない。ここで重要なのは、この演算子が特に副作用を持たず、どんな型でも右辺に取れることである。<code>b</code> の中身にフォーマット指定子はない (<code>%</code> などの記号が入力されないことが問題文から分かる) ので、誤って動作を壊してしまうおそれもない。