diff options
| author | nsfisis <nsfisis@gmail.com> | 2025-11-27 02:12:38 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2025-11-27 02:12:38 +0900 |
| commit | 2b102673ceb57081891e153b896aba5568dbc1f1 (patch) | |
| tree | 2bc76d5d9ef89e2e88c4f13de0ddb93c8b19a52e /services | |
| parent | 1c5bdf6d09a5f018ec54b88466361377b7373ded (diff) | |
| download | nsfisis.dev-2b102673ceb57081891e153b896aba5568dbc1f1.tar.gz nsfisis.dev-2b102673ceb57081891e153b896aba5568dbc1f1.tar.zst nsfisis.dev-2b102673ceb57081891e153b896aba5568dbc1f1.zip | |
feat(nuldoc/blog): New post /posts/2025-11-27/anybatross-writeup/
Diffstat (limited to 'services')
| -rw-r--r-- | services/nuldoc/content/posts/2025-11-27/anybatross-writeup.dj | 210 | ||||
| -rw-r--r-- | services/nuldoc/public/blog/posts/2/index.html | 52 | ||||
| -rw-r--r-- | services/nuldoc/public/blog/posts/2025-11-27/anybatross-writeup/index.html | 335 | ||||
| -rw-r--r-- | services/nuldoc/public/blog/posts/3/index.html | 46 | ||||
| -rw-r--r-- | services/nuldoc/public/blog/posts/4/index.html | 43 | ||||
| -rw-r--r-- | services/nuldoc/public/blog/posts/5/index.html | 46 | ||||
| -rw-r--r-- | services/nuldoc/public/blog/posts/6/index.html | 23 | ||||
| -rw-r--r-- | services/nuldoc/public/blog/posts/atom.xml | 10 | ||||
| -rw-r--r-- | services/nuldoc/public/blog/posts/index.html | 52 | ||||
| -rw-r--r-- | services/nuldoc/public/blog/tags/index.html | 6 | ||||
| -rw-r--r-- | services/nuldoc/public/blog/tags/perl/atom.xml | 10 | ||||
| -rw-r--r-- | services/nuldoc/public/blog/tags/perl/index.html | 26 | ||||
| -rw-r--r-- | services/nuldoc/public/blog/tags/ruby/atom.xml | 10 | ||||
| -rw-r--r-- | services/nuldoc/public/blog/tags/ruby/index.html | 26 | ||||
| -rw-r--r-- | services/nuldoc/public/blog/tags/yapc/atom.xml | 10 | ||||
| -rw-r--r-- | services/nuldoc/public/blog/tags/yapc/index.html | 26 |
16 files changed, 806 insertions, 125 deletions
diff --git a/services/nuldoc/content/posts/2025-11-27/anybatross-writeup.dj b/services/nuldoc/content/posts/2025-11-27/anybatross-writeup.dj new file mode 100644 index 0000000..d67d63d --- /dev/null +++ b/services/nuldoc/content/posts/2025-11-27/anybatross-writeup.dj @@ -0,0 +1,210 @@ +--- +[article] +uuid = "2ed2d400-b3f6-48bc-af27-19d9042875a0" +title = "カヤックさん開催のコードゴルフコンテスト Anybatross に参加して優勝した" +description = "YAPC::Fukuoka 2025 に際してカヤックさんが開催されていたコードゴルフコンテスト、Anybatross に参加して優勝した。" +tags = [ + "perl", + "ruby", + "yapc", +] + +[[article.revisions]] +date = "2025-11-27" +remark = "公開" +--- +{#intro} +# はじめに + +[YAPC::Fukuoka 2025](https://yapcjapan.org/2025fukuoka/) に際してカヤックさんが開催されていたコードゴルフコンテスト、[Anybatross](https://perlbatross.kayac.com/contest/2025fukuoka) に参加し、優勝した。 +この記事では自分の回答について解説する。 + +なお今回のシステムでは、現在の自分のスコア以下のコードを開催中も閲覧できる仕様だった。Hole 1 では特に使わなかったが、Hole 2 では途中他の方のコードをベースに進めた箇所がある (詳しくは後述)。 + +このコンテストは何度か開催されており、[前々回](https://perlbatross.kayac.com/contest/2024hiroshima) に参加したときは総合 2 位だった (前回開催は不参加)。 + +{#hole-1} +# Hole 1 + +{#answer} +## 回答 (45 byte) + +```perl +print$a+=$\=y/8B/0/+y/0469ADO-R//.$/,","for<> +``` + +Hole 1 については同一言語・同一スコアの回答が複数あるので詳細は省略する。 + + +{#hole-2} +# Hole 2 + +こちらは縮めていった過程も記載する。 + +{#answer-a} +## 回答 A (107 byte) + +最終スコアを見ると 4 位タイ (107 byte) が多く、3 位以上の回答と明確にアルゴリズムの差があるのでここから解説をスタートしようと思う。 + +```ruby +s=gets +?A.upto(?Z){(b,),m=s.scan(/(?=(.\B.))/).tally.max_by{_2} +m>1&&(s.gsub!b,it;$*<<it+?:+b)} +puts$**?,,s +``` + +変数名などの細かい差異を除けば他の 107 byte 回答と同じだが、 `String#scan` に渡す正規表現にこれを採用していたのは私だけだったのではないだろうか。 `/(?=(\S\S))/` や `/(?=(\w\w))/` と比べて短くはならないので意味はない。 + +`String#scan` はマッチした文字列を「消費」するので、重複した範囲を切り出す必要のある bi-gram の生成には使えない。そこで、肯定先読み (`(?=pattern)`) を使う。これは `^` や `\b` などと同様に、条件を指定しているだけでゼロ幅なので、`String#scan` に消費されない。これを使えば bi-gram の生成ができる。ただし、`s.scan(/\S\S/)` などと書いた場合とは異なり、返る配列が `[["la"], ["au"], ["un"], ...]` のような形でネストすることに注意。 + +出現頻度を調べるのには `Enumerable#tally` が使える。Perl に対する強烈な優位性はここで、これを使えばキーが各配列の要素、値が出現回数であるようなハッシュが一発で生成できる。 + +`Enumerable#max_by` で最頻値を取ってきた後は、多重代入を使って必要な値を取り出している。 + +```ruby +x = [["la"], 3] +(b,),m = x +# => b = "la", m = 3 +``` + +置換テーブルのデータは `$*` へと追加しているが、これは Ruby の特殊変数で、本来は `Object::ARGV` を指す。ここでは単に最初から空配列で初期化されている便利な入れ物として用いている。 + +その他、`?A` や `String#*`、`it`、numbered parameters などの細かいテクニックについては、「Ruby コードゴルフ」で調べるか、最近の Ruby のリリースノートを読むと見つかるはず。 + +{#answer-b} +## 回答 B (107 byte) + +回答 A をぐっと睨むと、`m>1&&(...)` の括弧を削りたくなる。しかしそれには `m>1&&` がどうしても邪魔になる。というわけで終了条件を工夫することでなんとか `m` を排除できないかを考えた。それがこちら。 + +```ruby +s=gets +?A.upto(?Z){(b,),=(?_+s).scan(/(?=(.\B.))/).tally.max_by{_2} +$*<<it+?:+b if s.gsub!b,it} +puts$**?,,s +``` + +`s` の先頭に番兵 `_` を置くことで、bi-gram の出現頻度がすべて 1 になったとき、`b` へと代入される値が「`_` + (`s` の先頭の文字)」になる。これを `String#gsub!` で置き換えようとすると、そのような文字列は `s` 中にないので置換が発生しない。`String#gsub!` は置換が起きなかったとき `nil` を返すので、これを使って条件分岐ができる。`&&` だと優先度の関係から `String#gsub!` の括弧が省略できないが、後置 if なら省略できる。 + +しかし、これだけでは回答 A とスコアは変わらない。これを短縮したものがこちら。 + +{#answer-c} +## 回答 C (106 byte) + +`Kernel#gets` は、入力を特殊変数 `$_` へ代入する。これは Perl 由来の挙動で、Ruby にはいくつか `$_` を参照するものがある。これを使って変数 `s` を置き換えると次のようになる。 + +```ruby +gets +?A.upto(?Z){(b,),="_#$_".scan(/(?=(.\B.))/).tally.max_by{_2} +$*<<it+?:+b if$_.gsub!b,it} +puts$**?,,$_ +``` + +これで 1 byte 縮む。 + +{#answer-d} +## 回答 D (104 byte) + +回答 C を眺めると、`b` への代入に文字を費やしすぎている。これを `String#gsub!` の第一引数に直接書いてはどうか。更に、直前のマッチしたパターンを指す特殊変数 `$&` を使えば、変数 `b` を排除できる。それがこちら。 + +```ruby +gets +?A.upto(?Z){$*<<it+?:+$&if$_.gsub!"_#$_".scan(/(?=(.\B.))/).tally.max_by{_2}[0][0],it} +puts$**?,,$_ +``` + +コードゴルフとして `[0][0]` は気になるところだが、それでも 2 byte 一気に縮まった。 + +{#answer-e} +## 回答 E (103 byte) + +回答 D を提出したことで tompng 氏のスコアを越え、氏のコードを閲覧できるようになった。そこから少し変更したものが、mame 氏と (変数名などの些事を除いて) 同じ以下のコードである。 + +```ruby +s=gets +?A.upto(?Z){s.scan(/(?=(.\B.))/).tally.max_by{_2}in[b],1or($*<<it+?:+b;s.gsub!b,it)} +puts$**?,,s +``` + +ここまでとは大きく異なる戦略で終了条件を判定している。使われているのはパターンマッチで、`in` がマッチの有無を `true` / `false` で返すことを利用している。`or` を用いて、最頻値の出現回数が 1 でないなら置換処理を継続する。 + +パターンマッチの利用については途中何度か検討したが、1 でないときに処理を実行するという方針で実装しようとしてしまい、上手く短縮できなかった。 + +```ruby +# これは 106 byte +s=gets +?A.upto(?Z){s.scan(/(?=(.\B.))/).tally.max_by{_2}in[b],2..and($*<<it+?:+b;s.gsub!b,it)} +puts$**?,,s +``` + + +{#answer-f} +## 回答 F (103 byte) + +さて、ヒントを求めて [前回開催の公式解説ブログ](https://techblog.kayac.com/yapc2024hakodate-perlbatross-result) を読んでいたところ、次のような興味深い記述を発見した。 + +> 参加者のみなさんの最短解はshebangを書いてPerlのオプションを設定していい感じにやるものでしたが、 +> (中略) +> 今回はチート抑止みたいなところの意図でperlコマンドを実行する方式になったので、ちゃんとshebangを書けば効くようになっていたのでした。 + +Shebang が使えるのなら、Ruby にも Perl に由来するオプションがいくつかあるので、似たような手段で短縮できるのではないか? + +`ruby` で `-p` を付けると、以下のようなコードを書いたかのように動作する。 + +```ruby +while gets + ... # 記載したコードの処理 + puts $_ +end +``` + +また、`Kernel#gsub` という `$_ = $_.gsub(...)` と同様の処理をおこなうメソッドが生えてくる。今回は `String#gsub!` も使うので、shebang の分を回収できれば短縮になりそうだ。 + +というわけで、実はこれまでも shebang での短縮は何度か試していた。しかし、いずれも 1 byte 増えたり変化しなかったりで成果を上げられずにいた。回答 E についても同様に、以下のようなコードを作っていた。 + +```ruby +#!ruby -p +?A.upto(?Z){$_.scan(/(?=(.\B.))/).tally.max_by{_2}in[b],1or($*<<it+?:+b;gsub b,it)} +puts$**?, +``` + +しかしこれは 103 byte で縮められない。にっくきは `gsub` と `b` の間のスペースである。せっかく `s.gsub!` を `gsub` にしたのに、後ろが記号でなくなったことでスペースが生じている。といって、括弧を付けるのも上手くはいかない。 + +```ruby +# これも同じく 103 byte +#!ruby -p +?A.upto(?Z){$_.scan(/(?=(.\B.))/).tally.max_by{_2}in[b],1or$*<<it+?:+b&&gsub(b,it)} +puts$**?, +``` + +外側の括弧を移動させてくれば `gsub` と `b` の間のスペースを消せるが、`;` を `&&` にせねばならず失敗する。この問題を解決したのが最終回答の 102 byte コードである。 + + +{#answer-g} +## 最終回答 (102 byte) + +```ruby +#!ruby -p +?A.upto(?Z){$_.scan(/(?=(.\B.))/).tally.max_by{_2}in[b],1or$*<<it+?:+b%gsub(b,it)} +puts$**?, +``` + +`String#%` は文字列のフォーマット処理をおこなう演算子だが、ここでは特にフォーマット目的で呼んでいるわけではない。ここで重要なのは、この演算子が特に副作用を持たず、どんな型でも右辺に取れることである。`b` の中身にフォーマット指定子はない (`%` などの記号が入力されないことが問題文から分かる) ので、誤って動作を壊してしまうおそれもない。 + +これによって Hole 2 の単独 1 位スコアとなった。 + + +{#llm} +# LLM のコードゴルフ性能 + +ところで、今回スコア短縮に行き詰まったあたりから LLM を使ってみた (コンテストのレギュレーションとして明示的に利用が許可されている)。 + +結論から言うと役には立たなかった。サンプルコードを縮めるくらいの用途には使えるかもしれないが (未検証)、すでに人間がある程度のところまで縮めたコードを更に短縮するのはまだ荷が重いようだ。 +そもそもそれで縮まって楽しいのかという別の問題もある。 + +なお、LLM は文字数カウントを大の苦手としているので、縮めた (と言い張っている) コードを `wc` コマンドに渡し、その結果を LLM に見てもらった方がよい。 + + +{#outro} +# おわりに + +楽しかったです。運営のみなさま、ありがとうございました! diff --git a/services/nuldoc/public/blog/posts/2/index.html b/services/nuldoc/public/blog/posts/2/index.html index 70f6cf2..d17ad34 100644 --- a/services/nuldoc/public/blog/posts/2/index.html +++ b/services/nuldoc/public/blog/posts/2/index.html @@ -67,6 +67,32 @@ </div> </nav> <article class="post-entry"> + <a href="/posts/2025-02-24/phpcon-nagoya-2025-report/"> + <header class="entry-header"> + <h2>PHP カンファレンス名古屋 2025 参加レポ</h2> + </header> + <section class="entry-content"> + <p> + 2025-02-22 に開催された、PHP カンファレンス名古屋 2025 に参加した。 + </p> + </section> + <footer class="entry-footer"> + <time datetime="2025-02-24">2025-02-24</time> 投稿 + <ul class="entry-tags"> + <li class="tag"> + カンファレンス + </li> + <li class="tag"> + PHP + </li> + <li class="tag"> + PHP カンファレンス名古屋 + </li> + </ul> + </footer> + </a> + </article> + <article class="post-entry"> <a href="/posts/2025-01-26/yaml-breaking-changes-between-v1-1-and-v1-2/"> <header class="entry-header"> <h2>【YAML】YAML 1.1 と YAML 1.2 の主な破壊的変更</h2> @@ -268,32 +294,6 @@ </footer> </a> </article> - <article class="post-entry"> - <a href="/posts/2024-04-29/zsh-file-completion-for-composer-custom-commands/"> - <header class="entry-header"> - <h2>【Zsh】 Composer のカスタムコマンドに対する Zsh 補完で引数にファイルを補完させる</h2> - </header> - <section class="entry-content"> - <p> - Zsh の Composer に対する補完はカスタムコマンドやその引数を補完しない。カスタムコマンドの引数としてファイルを補完させる方法を調べた。 - </p> - </section> - <footer class="entry-footer"> - <time datetime="2024-04-29">2024-04-29</time> 投稿 - <ul class="entry-tags"> - <li class="tag"> - Composer - </li> - <li class="tag"> - PHP - </li> - <li class="tag"> - Zsh - </li> - </ul> - </footer> - </a> - </article> <nav class="pagination"> <div class="pagination-prev"> <a href="/posts/">前へ</a> 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 new file mode 100644 index 0000000..3b321e3 --- /dev/null +++ b/services/nuldoc/public/blog/posts/2025-11-27/anybatross-writeup/index.html @@ -0,0 +1,335 @@ +<!DOCTYPE html> +<html lang="ja-JP"> + <head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <meta name="author" content="nsfisis"> + <meta name="copyright" content="© 2025 nsfisis"> + <meta name="description" content="YAPC::Fukuoka 2025 に際してカヤックさんが開催されていたコードゴルフコンテスト、Anybatross に参加して優勝した。"> + <meta name="keywords" content="Perl,Ruby,YAPC"> + <meta property="og:type" content="article"> + <meta property="og:title" content="カヤックさん開催のコードゴルフコンテスト Anybatross に参加して優勝した|REPL: Rest-Eat-Program Loop"> + <meta property="og:description" content="YAPC::Fukuoka 2025 に際してカヤックさんが開催されていたコードゴルフコンテスト、Anybatross に参加して優勝した。"> + <meta property="og:site_name" content="REPL: Rest-Eat-Program Loop"> + <meta property="og:locale" content="ja_JP"> + <meta name="Hatena::Bookmark" content="nocomment"> + <link rel="icon" type="image/svg+xml" href="/favicon.svg"> + <title>カヤックさん開催のコードゴルフコンテスト Anybatross に参加して優勝した|REPL: Rest-Eat-Program Loop</title> + <link rel="stylesheet" href="/style.css?h=a30308eaf2992194b70031439b7401aa"> + </head> + <body class="single"> + <header class="header"> + <div class="site-logo"> + <a href="https://nsfisis.dev/">nsfisis.dev</a> + </div> + <div class="site-name"> + REPL: Rest-Eat-Program Loop + </div> + <nav class="nav"> + <ul> + <li> + <a href="https://about.nsfisis.dev/">About</a> + </li> + <li> + <a href="/posts/">Posts</a> + </li> + <li> + <a href="/tags/">Tags</a> + </li> + </ul> + </nav> + </header> + <main class="main"> + <article class="post-single"> + <header class="post-header"> + <h1 class="post-title">カヤックさん開催のコードゴルフコンテスト Anybatross に参加して優勝した</h1> + <ul class="post-tags"> + <li class="tag"> + <a href="/tags/perl/">Perl</a> + </li> + <li class="tag"> + <a href="/tags/ruby/">Ruby</a> + </li> + <li class="tag"> + <a href="/tags/yapc/">YAPC</a> + </li> + </ul> + </header> + <nav class="toc"> + <h2>目次</h2> + <ul> + <li> + <a href="#section--intro">はじめに</a> + </li> + <li> + <a href="#section--hole-1">Hole 1</a> + <ul> + <li> + <a href="#section--hole-1--answer">回答 (45 byte)</a> + </li> + </ul> + </li> + <li> + <a href="#section--hole-2">Hole 2</a> + <ul> + <li> + <a href="#section--hole-2--answer-a">回答 A (107 byte)</a> + </li> + <li> + <a href="#section--hole-2--answer-b">回答 B (107 byte)</a> + </li> + <li> + <a href="#section--hole-2--answer-c">回答 C (106 byte)</a> + </li> + <li> + <a href="#section--hole-2--answer-d">回答 D (104 byte)</a> + </li> + <li> + <a href="#section--hole-2--answer-e">回答 E (103 byte)</a> + </li> + <li> + <a href="#section--hole-2--answer-f">回答 F (103 byte)</a> + </li> + <li> + <a href="#section--hole-2--answer-g">最終回答 (102 byte)</a> + </li> + </ul> + </li> + <li> + <a href="#section--llm">LLM のコードゴルフ性能</a> + </li> + <li> + <a href="#section--outro">おわりに</a> + </li> + </ul> + </nav> + <div class="post-content"> + <section id="changelog"> + <h2><a href="#changelog">更新履歴</a></h2> + <ol> + <li class="revision"> + <time datetime="2025-11-27">2025-11-27</time>: 公開 + </li> + </ol> + </section> + <section id="section--intro"> + <h2><a href="#section--intro">はじめに</a></h2> + <p> + <a href="https://yapcjapan.org/2025fukuoka/" rel="noreferrer" target="_blank">YAPC::Fukuoka 2025</a> に際してカヤックさんが開催されていたコードゴルフコンテスト、<a href="https://perlbatross.kayac.com/contest/2025fukuoka" rel="noreferrer" target="_blank">Anybatross</a> に参加し、優勝した。この記事では自分の回答について解説する。 + </p> + <p> + なお今回のシステムでは、現在の自分のスコア以下のコードを開催中も閲覧できる仕様だった。Hole 1 では特に使わなかったが、Hole 2 では途中他の方のコードをベースに進めた箇所がある (詳しくは後述)。 + </p> + <p> + このコンテストは何度か開催されており、<a href="https://perlbatross.kayac.com/contest/2024hiroshima" rel="noreferrer" target="_blank">前々回</a> に参加したときは総合 2 位だった (前回開催は不参加)。 + </p> + </section> + <section id="section--hole-1"> + <h2><a href="#section--hole-1">Hole 1</a></h2> + <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"><></span></span></code></pre> + </div> + <p> + Hole 1 については同一言語・同一スコアの回答が複数あるので詳細は省略する。 + </p> + </section> + </section> + <section id="section--hole-2"> + <h2><a href="#section--hole-2">Hole 2</a></h2> + <p> + こちらは縮めていった過程も記載する。 + </p> + <section id="section--hole-2--answer-a"> + <h3><a href="#section--hole-2--answer-a">回答 A (107 byte)</a></h3> + <p> + 最終スコアを見ると 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">&&</span><span style="color:#24292E">(s.</span><span style="color:#6F42C1">gsub!b</span><span style="color:#24292E">,it;$*</span><span style="color:#D73A49"><<</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> + </div> + <p> + 変数名などの細かい差異を除けば他の 107 byte 回答と同じだが、 <code>String#scan</code> に渡す正規表現にこれを採用していたのは私だけだったのではないだろうか。 <code>/(?=(\S\S))/</code> や <code>/(?=(\w\w))/</code> と比べて短くはならないので意味はない。 + </p> + <p> + <code>String#scan</code> はマッチした文字列を「消費」するので、重複した範囲を切り出す必要のある bi-gram の生成には使えない。そこで、肯定先読み (<code>(?=pattern)</code>) を使う。これは <code>^</code> や <code>\b</code> などと同様に、条件を指定しているだけでゼロ幅なので、<code>String#scan</code> に消費されない。これを使えば bi-gram の生成ができる。ただし、<code>s.scan(/\S\S/)</code> などと書いた場合とは異なり、返る配列が <code>[["la"], ["au"], ["un"], ...]</code> のような形でネストすることに注意。 + </p> + <p> + 出現頻度を調べるのには <code>Enumerable#tally</code> が使える。Perl に対する強烈な優位性はここで、これを使えばキーが各配列の要素、値が出現回数であるようなハッシュが一発で生成できる。 + </p> + <p> + <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> + </div> + <p> + 置換テーブルのデータは <code>$*</code> へと追加しているが、これは Ruby の特殊変数で、本来は <code>Object::ARGV</code> を指す。ここでは単に最初から空配列で初期化されている便利な入れ物として用いている。 + </p> + <p> + その他、<code>?A</code> や <code>String#*</code>、<code>it</code>、numbered parameters などの細かいテクニックについては、「Ruby コードゴルフ」で調べるか、最近の Ruby のリリースノートを読むと見つかるはず。 + </p> + </section> + <section id="section--hole-2--answer-b"> + <h3><a href="#section--hole-2--answer-b">回答 B (107 byte)</a></h3> + <p> + 回答 A をぐっと睨むと、<code>m>1&&(...)</code> の括弧を削りたくなる。しかしそれには <code>m>1&&</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"><<</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> + </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>&&</code> だと優先度の関係から <code>String#gsub!</code> の括弧が省略できないが、後置 if なら省略できる。 + </p> + <p> + しかし、これだけでは回答 A とスコアは変わらない。これを短縮したものがこちら。 + </p> + </section> + <section id="section--hole-2--answer-c"> + <h3><a href="#section--hole-2--answer-c">回答 C (106 byte)</a></h3> + <p> + <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"><<</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> + </div> + <p> + これで 1 byte 縮む。 + </p> + </section> + <section id="section--hole-2--answer-d"> + <h3><a href="#section--hole-2--answer-d">回答 D (104 byte)</a></h3> + <p> + 回答 C を眺めると、<code>b</code> への代入に文字を費やしすぎている。これを <code>String#gsub!</code> の第一引数に直接書いてはどうか。更に、直前のマッチしたパターンを指す特殊変数 <code>$&</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"><<</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">$&</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> + </div> + <p> + コードゴルフとして <code>[0][0]</code> は気になるところだが、それでも 2 byte 一気に縮まった。 + </p> + </section> + <section id="section--hole-2--answer-e"> + <h3><a href="#section--hole-2--answer-e">回答 E (103 byte)</a></h3> + <p> + 回答 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"><<</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> + </div> + <p> + ここまでとは大きく異なる戦略で終了条件を判定している。使われているのはパターンマッチで、<code>in</code> がマッチの有無を <code>true</code> / <code>false</code> で返すことを利用している。<code>or</code> を用いて、最頻値の出現回数が 1 でないなら置換処理を継続する。 + </p> + <p> + パターンマッチの利用については途中何度か検討したが、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"><<</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> + </div> + </section> + <section id="section--hole-2--answer-f"> + <h3><a href="#section--hole-2--answer-f">回答 F (103 byte)</a></h3> + <p> + さて、ヒントを求めて <a href="https://techblog.kayac.com/yapc2024hakodate-perlbatross-result" rel="noreferrer" target="_blank">前回開催の公式解説ブログ</a> を読んでいたところ、次のような興味深い記述を発見した。 + </p> + <blockquote> + <p> + 参加者のみなさんの最短解はshebangを書いてPerlのオプションを設定していい感じにやるものでしたが、(中略) 今回はチート抑止みたいなところの意図でperlコマンドを実行する方式になったので、ちゃんとshebangを書けば効くようになっていたのでした。 + </p> + </blockquote> + <p> + Shebang が使えるのなら、Ruby にも Perl に由来するオプションがいくつかあるので、似たような手段で短縮できるのではないか? + </p> + <p> + <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> + </div> + <p> + また、<code>Kernel#gsub</code> という <code>$_ = $_.gsub(...)</code> と同様の処理をおこなうメソッドが生えてくる。今回は <code>String#gsub!</code> も使うので、shebang の分を回収できれば短縮になりそうだ。 + </p> + <p> + というわけで、実はこれまでも 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"><<</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> + </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"><<</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> + </div> + <p> + 外側の括弧を移動させてくれば <code>gsub</code> と <code>b</code> の間のスペースを消せるが、<code>;</code> を <code>&&</code> にせねばならず失敗する。この問題を解決したのが最終回答の 102 byte コードである。 + </p> + </section> + <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"><<</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> + </div> + <p> + <code>String#%</code> は文字列のフォーマット処理をおこなう演算子だが、ここでは特にフォーマット目的で呼んでいるわけではない。ここで重要なのは、この演算子が特に副作用を持たず、どんな型でも右辺に取れることである。<code>b</code> の中身にフォーマット指定子はない (<code>%</code> などの記号が入力されないことが問題文から分かる) ので、誤って動作を壊してしまうおそれもない。 + </p> + <p> + これによって Hole 2 の単独 1 位スコアとなった。 + </p> + </section> + </section> + <section id="section--llm"> + <h2><a href="#section--llm">LLM のコードゴルフ性能</a></h2> + <p> + ところで、今回スコア短縮に行き詰まったあたりから LLM を使ってみた (コンテストのレギュレーションとして明示的に利用が許可されている)。 + </p> + <p> + 結論から言うと役には立たなかった。サンプルコードを縮めるくらいの用途には使えるかもしれないが (未検証)、すでに人間がある程度のところまで縮めたコードを更に短縮するのはまだ荷が重いようだ。そもそもそれで縮まって楽しいのかという別の問題もある。 + </p> + <p> + なお、LLM は文字数カウントを大の苦手としているので、縮めた (と言い張っている) コードを <code>wc</code> コマンドに渡し、その結果を LLM に見てもらった方がよい。 + </p> + </section> + <section id="section--outro"> + <h2><a href="#section--outro">おわりに</a></h2> + <p> + 楽しかったです。運営のみなさま、ありがとうございました! + </p> + </section> + </div> + </article> + </main> + <footer class="footer"> + © 2021 nsfisis + </footer> + </body> +</html> diff --git a/services/nuldoc/public/blog/posts/3/index.html b/services/nuldoc/public/blog/posts/3/index.html index f926085..38432fc 100644 --- a/services/nuldoc/public/blog/posts/3/index.html +++ b/services/nuldoc/public/blog/posts/3/index.html @@ -70,6 +70,32 @@ </div> </nav> <article class="post-entry"> + <a href="/posts/2024-04-29/zsh-file-completion-for-composer-custom-commands/"> + <header class="entry-header"> + <h2>【Zsh】 Composer のカスタムコマンドに対する Zsh 補完で引数にファイルを補完させる</h2> + </header> + <section class="entry-content"> + <p> + Zsh の Composer に対する補完はカスタムコマンドやその引数を補完しない。カスタムコマンドの引数としてファイルを補完させる方法を調べた。 + </p> + </section> + <footer class="entry-footer"> + <time datetime="2024-04-29">2024-04-29</time> 投稿 + <ul class="entry-tags"> + <li class="tag"> + Composer + </li> + <li class="tag"> + PHP + </li> + <li class="tag"> + Zsh + </li> + </ul> + </footer> + </a> + </article> + <article class="post-entry"> <a href="/posts/2024-04-21/pipefail-option-in-gitlab-ci-cd/"> <header class="entry-header"> <h2>【GitLab】 GitLab CI/CD 上での bash/sh は pipefail が有効になっている</h2> @@ -272,26 +298,6 @@ </footer> </a> </article> - <article class="post-entry"> - <a href="/posts/2023-12-03/isucon-13/"> - <header class="entry-header"> - <h2>ISUCON 13 に参加した</h2> - </header> - <section class="entry-content"> - <p> - ISUCON 13 に参加した。チーム名「うつしもゆ」、最終スコア 13,580 点 - </p> - </section> - <footer class="entry-footer"> - <time datetime="2023-12-03">2023-12-03</time> 投稿 - <ul class="entry-tags"> - <li class="tag"> - ISUCON - </li> - </ul> - </footer> - </a> - </article> <nav class="pagination"> <div class="pagination-prev"> <a href="/posts/2/">前へ</a> diff --git a/services/nuldoc/public/blog/posts/4/index.html b/services/nuldoc/public/blog/posts/4/index.html index 11bbb27..78a08f3 100644 --- a/services/nuldoc/public/blog/posts/4/index.html +++ b/services/nuldoc/public/blog/posts/4/index.html @@ -70,6 +70,26 @@ </div> </nav> <article class="post-entry"> + <a href="/posts/2023-12-03/isucon-13/"> + <header class="entry-header"> + <h2>ISUCON 13 に参加した</h2> + </header> + <section class="entry-content"> + <p> + ISUCON 13 に参加した。チーム名「うつしもゆ」、最終スコア 13,580 点 + </p> + </section> + <footer class="entry-footer"> + <time datetime="2023-12-03">2023-12-03</time> 投稿 + <ul class="entry-tags"> + <li class="tag"> + ISUCON + </li> + </ul> + </footer> + </a> + </article> + <article class="post-entry"> <a href="/posts/2023-10-13/i-entered-the-open-university-of-japan/"> <header class="entry-header"> <h2>放送大学に入学しました</h2> @@ -260,29 +280,6 @@ </footer> </a> </article> - <article class="post-entry"> - <a href="/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/"> - <header class="entry-header"> - <h2>PHPerKaigi 2023: ボツになったトークン問題 その 1</h2> - </header> - <section class="entry-content"> - <p> - 来年の PHPerKaigi 2023 でデジタルサーカス株式会社から出題予定のトークン問題のうち、ボツになった問題を公開する (その 1)。 - </p> - </section> - <footer class="entry-footer"> - <time datetime="2022-10-23">2022-10-23</time> 投稿 - <ul class="entry-tags"> - <li class="tag"> - PHP - </li> - <li class="tag"> - PHPerKaigi - </li> - </ul> - </footer> - </a> - </article> <nav class="pagination"> <div class="pagination-prev"> <a href="/posts/3/">前へ</a> diff --git a/services/nuldoc/public/blog/posts/5/index.html b/services/nuldoc/public/blog/posts/5/index.html index a5b7622..1ae68d1 100644 --- a/services/nuldoc/public/blog/posts/5/index.html +++ b/services/nuldoc/public/blog/posts/5/index.html @@ -67,6 +67,29 @@ </div> </nav> <article class="post-entry"> + <a href="/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/"> + <header class="entry-header"> + <h2>PHPerKaigi 2023: ボツになったトークン問題 その 1</h2> + </header> + <section class="entry-content"> + <p> + 来年の PHPerKaigi 2023 でデジタルサーカス株式会社から出題予定のトークン問題のうち、ボツになった問題を公開する (その 1)。 + </p> + </section> + <footer class="entry-footer"> + <time datetime="2022-10-23">2022-10-23</time> 投稿 + <ul class="entry-tags"> + <li class="tag"> + PHP + </li> + <li class="tag"> + PHPerKaigi + </li> + </ul> + </footer> + </a> + </article> + <article class="post-entry"> <a href="/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line/"> <header class="entry-header"> <h2>【PHP】 fizzbuzz を書く。1行あたり2文字で。</h2> @@ -260,29 +283,6 @@ </footer> </a> </article> - <article class="post-entry"> - <a href="/posts/2021-10-02/ruby-then-keyword-and-case-in/"> - <header class="entry-header"> - <h2>【Ruby】 then キーワードと case in</h2> - </header> - <section class="entry-content"> - <p> - Ruby 3.0 で追加される case in 構文と、then キーワードについて。 - </p> - </section> - <footer class="entry-footer"> - <time datetime="2021-10-02">2021-10-02</time> 投稿 - <ul class="entry-tags"> - <li class="tag"> - Ruby - </li> - <li class="tag"> - Ruby 3 - </li> - </ul> - </footer> - </a> - </article> <nav class="pagination"> <div class="pagination-prev"> <a href="/posts/4/">前へ</a> diff --git a/services/nuldoc/public/blog/posts/6/index.html b/services/nuldoc/public/blog/posts/6/index.html index 3564215..6067a5e 100644 --- a/services/nuldoc/public/blog/posts/6/index.html +++ b/services/nuldoc/public/blog/posts/6/index.html @@ -63,6 +63,29 @@ </div> </nav> <article class="post-entry"> + <a href="/posts/2021-10-02/ruby-then-keyword-and-case-in/"> + <header class="entry-header"> + <h2>【Ruby】 then キーワードと case in</h2> + </header> + <section class="entry-content"> + <p> + Ruby 3.0 で追加される case in 構文と、then キーワードについて。 + </p> + </section> + <footer class="entry-footer"> + <time datetime="2021-10-02">2021-10-02</time> 投稿 + <ul class="entry-tags"> + <li class="tag"> + Ruby + </li> + <li class="tag"> + Ruby 3 + </li> + </ul> + </footer> + </a> + </article> + <article class="post-entry"> <a href="/posts/2021-10-02/rust-where-are-primitive-types-from/"> <header class="entry-header"> <h2>Rust のプリミティブ型はどこからやって来るか</h2> diff --git a/services/nuldoc/public/blog/posts/atom.xml b/services/nuldoc/public/blog/posts/atom.xml index 594527b..4c02c04 100644 --- a/services/nuldoc/public/blog/posts/atom.xml +++ b/services/nuldoc/public/blog/posts/atom.xml @@ -7,7 +7,15 @@ <author> <name>nsfisis</name> </author> - <updated>2025-11-09T00:00:00+09:00</updated> + <updated>2025-11-27T00:00:00+09:00</updated> + <entry> + <id>urn:uuid:2ed2d400-b3f6-48bc-af27-19d9042875a0</id> + <link rel="alternate" href="https://blog.nsfisis.dev/posts/2025-11-27/anybatross-writeup/"></link> + <title>カヤックさん開催のコードゴルフコンテスト Anybatross に参加して優勝した</title> + <summary>YAPC::Fukuoka 2025 に際してカヤックさんが開催されていたコードゴルフコンテスト、Anybatross に参加して優勝した。</summary> + <published>2025-11-27T00:00:00+09:00</published> + <updated>2025-11-27T00:00:00+09:00</updated> + </entry> <entry> <id>urn:uuid:68ce6d2f-81ba-47ca-93d3-26553fc73807</id> <link rel="alternate" href="https://blog.nsfisis.dev/posts/2025-11-09/rubiks-cube-blindfolded-first-success/"></link> diff --git a/services/nuldoc/public/blog/posts/index.html b/services/nuldoc/public/blog/posts/index.html index 8fd7538..c43c6ee 100644 --- a/services/nuldoc/public/blog/posts/index.html +++ b/services/nuldoc/public/blog/posts/index.html @@ -63,6 +63,32 @@ </div> </nav> <article class="post-entry"> + <a href="/posts/2025-11-27/anybatross-writeup/"> + <header class="entry-header"> + <h2>カヤックさん開催のコードゴルフコンテスト Anybatross に参加して優勝した</h2> + </header> + <section class="entry-content"> + <p> + YAPC::Fukuoka 2025 に際してカヤックさんが開催されていたコードゴルフコンテスト、Anybatross に参加して優勝した。 + </p> + </section> + <footer class="entry-footer"> + <time datetime="2025-11-27">2025-11-27</time> 投稿 + <ul class="entry-tags"> + <li class="tag"> + Perl + </li> + <li class="tag"> + Ruby + </li> + <li class="tag"> + YAPC + </li> + </ul> + </footer> + </a> + </article> + <article class="post-entry"> <a href="/posts/2025-11-09/rubiks-cube-blindfolded-first-success/"> <header class="entry-header"> <h2>ルービックキューブを目隠しで揃えることに初成功した</h2> @@ -255,32 +281,6 @@ </footer> </a> </article> - <article class="post-entry"> - <a href="/posts/2025-02-24/phpcon-nagoya-2025-report/"> - <header class="entry-header"> - <h2>PHP カンファレンス名古屋 2025 参加レポ</h2> - </header> - <section class="entry-content"> - <p> - 2025-02-22 に開催された、PHP カンファレンス名古屋 2025 に参加した。 - </p> - </section> - <footer class="entry-footer"> - <time datetime="2025-02-24">2025-02-24</time> 投稿 - <ul class="entry-tags"> - <li class="tag"> - カンファレンス - </li> - <li class="tag"> - PHP - </li> - <li class="tag"> - PHP カンファレンス名古屋 - </li> - </ul> - </footer> - </a> - </article> <nav class="pagination"> <div class="pagination-prev"> </div> diff --git a/services/nuldoc/public/blog/tags/index.html b/services/nuldoc/public/blog/tags/index.html index 2ea53e0..3e6e902 100644 --- a/services/nuldoc/public/blog/tags/index.html +++ b/services/nuldoc/public/blog/tags/index.html @@ -228,7 +228,7 @@ <h2>Perl</h2> </header> <footer class="entry-footer"> - 1件の記事 + 2件の記事 </footer> </a> </article> @@ -348,7 +348,7 @@ <h2>Ruby</h2> </header> <footer class="entry-footer"> - 3件の記事 + 4件の記事 </footer> </a> </article> @@ -468,7 +468,7 @@ <h2>YAPC</h2> </header> <footer class="entry-footer"> - 1件の記事 + 2件の記事 </footer> </a> </article> diff --git a/services/nuldoc/public/blog/tags/perl/atom.xml b/services/nuldoc/public/blog/tags/perl/atom.xml index b0f8e0d..a641e25 100644 --- a/services/nuldoc/public/blog/tags/perl/atom.xml +++ b/services/nuldoc/public/blog/tags/perl/atom.xml @@ -7,7 +7,15 @@ <author> <name>nsfisis</name> </author> - <updated>2024-02-10T00:00:00+09:00</updated> + <updated>2025-11-27T00:00:00+09:00</updated> + <entry> + <id>urn:uuid:2ed2d400-b3f6-48bc-af27-19d9042875a0</id> + <link rel="alternate" href="https://blog.nsfisis.dev/posts/2025-11-27/anybatross-writeup/"></link> + <title>カヤックさん開催のコードゴルフコンテスト Anybatross に参加して優勝した</title> + <summary>YAPC::Fukuoka 2025 に際してカヤックさんが開催されていたコードゴルフコンテスト、Anybatross に参加して優勝した。</summary> + <published>2025-11-27T00:00:00+09:00</published> + <updated>2025-11-27T00:00:00+09:00</updated> + </entry> <entry> <id>urn:uuid:230a0048-93c0-4aac-91ef-bb3108f3e587</id> <link rel="alternate" href="https://blog.nsfisis.dev/posts/2024-02-10/yapcjapan-2024-report/"></link> diff --git a/services/nuldoc/public/blog/tags/perl/index.html b/services/nuldoc/public/blog/tags/perl/index.html index 9393d67..e98a9f6 100644 --- a/services/nuldoc/public/blog/tags/perl/index.html +++ b/services/nuldoc/public/blog/tags/perl/index.html @@ -45,6 +45,32 @@ <h1>タグ「Perl」一覧</h1> </header> <article class="post-entry"> + <a href="/posts/2025-11-27/anybatross-writeup/"> + <header class="entry-header"> + <h2>カヤックさん開催のコードゴルフコンテスト Anybatross に参加して優勝した</h2> + </header> + <section class="entry-content"> + <p> + YAPC::Fukuoka 2025 に際してカヤックさんが開催されていたコードゴルフコンテスト、Anybatross に参加して優勝した。 + </p> + </section> + <footer class="entry-footer"> + <time datetime="2025-11-27">2025-11-27</time> 投稿 + <ul class="entry-tags"> + <li class="tag"> + Perl + </li> + <li class="tag"> + Ruby + </li> + <li class="tag"> + YAPC + </li> + </ul> + </footer> + </a> + </article> + <article class="post-entry"> <a href="/posts/2024-02-10/yapcjapan-2024-report/"> <header class="entry-header"> <h2>YAPC::Hiroshima 2024 参加レポ</h2> diff --git a/services/nuldoc/public/blog/tags/ruby/atom.xml b/services/nuldoc/public/blog/tags/ruby/atom.xml index 04d572e..3237c91 100644 --- a/services/nuldoc/public/blog/tags/ruby/atom.xml +++ b/services/nuldoc/public/blog/tags/ruby/atom.xml @@ -7,7 +7,15 @@ <author> <name>nsfisis</name> </author> - <updated>2025-04-20T00:00:00+09:00</updated> + <updated>2025-11-27T00:00:00+09:00</updated> + <entry> + <id>urn:uuid:2ed2d400-b3f6-48bc-af27-19d9042875a0</id> + <link rel="alternate" href="https://blog.nsfisis.dev/posts/2025-11-27/anybatross-writeup/"></link> + <title>カヤックさん開催のコードゴルフコンテスト Anybatross に参加して優勝した</title> + <summary>YAPC::Fukuoka 2025 に際してカヤックさんが開催されていたコードゴルフコンテスト、Anybatross に参加して優勝した。</summary> + <published>2025-11-27T00:00:00+09:00</published> + <updated>2025-11-27T00:00:00+09:00</updated> + </entry> <entry> <id>urn:uuid:039b3dff-3b75-46b7-a731-9a3a0ff8e21f</id> <link rel="alternate" href="https://blog.nsfisis.dev/posts/2025-04-20/trick-2025-most-ruby-on-ruby-award/"></link> diff --git a/services/nuldoc/public/blog/tags/ruby/index.html b/services/nuldoc/public/blog/tags/ruby/index.html index e6d3aee..7f78656 100644 --- a/services/nuldoc/public/blog/tags/ruby/index.html +++ b/services/nuldoc/public/blog/tags/ruby/index.html @@ -45,6 +45,32 @@ <h1>タグ「Ruby」一覧</h1> </header> <article class="post-entry"> + <a href="/posts/2025-11-27/anybatross-writeup/"> + <header class="entry-header"> + <h2>カヤックさん開催のコードゴルフコンテスト Anybatross に参加して優勝した</h2> + </header> + <section class="entry-content"> + <p> + YAPC::Fukuoka 2025 に際してカヤックさんが開催されていたコードゴルフコンテスト、Anybatross に参加して優勝した。 + </p> + </section> + <footer class="entry-footer"> + <time datetime="2025-11-27">2025-11-27</time> 投稿 + <ul class="entry-tags"> + <li class="tag"> + Perl + </li> + <li class="tag"> + Ruby + </li> + <li class="tag"> + YAPC + </li> + </ul> + </footer> + </a> + </article> + <article class="post-entry"> <a href="/posts/2025-04-20/trick-2025-most-ruby-on-ruby-award/"> <header class="entry-header"> <h2>RubyKaigi 2025 の TRICK で入賞した</h2> diff --git a/services/nuldoc/public/blog/tags/yapc/atom.xml b/services/nuldoc/public/blog/tags/yapc/atom.xml index f9c92e6..b8e90c2 100644 --- a/services/nuldoc/public/blog/tags/yapc/atom.xml +++ b/services/nuldoc/public/blog/tags/yapc/atom.xml @@ -7,7 +7,15 @@ <author> <name>nsfisis</name> </author> - <updated>2024-02-10T00:00:00+09:00</updated> + <updated>2025-11-27T00:00:00+09:00</updated> + <entry> + <id>urn:uuid:2ed2d400-b3f6-48bc-af27-19d9042875a0</id> + <link rel="alternate" href="https://blog.nsfisis.dev/posts/2025-11-27/anybatross-writeup/"></link> + <title>カヤックさん開催のコードゴルフコンテスト Anybatross に参加して優勝した</title> + <summary>YAPC::Fukuoka 2025 に際してカヤックさんが開催されていたコードゴルフコンテスト、Anybatross に参加して優勝した。</summary> + <published>2025-11-27T00:00:00+09:00</published> + <updated>2025-11-27T00:00:00+09:00</updated> + </entry> <entry> <id>urn:uuid:230a0048-93c0-4aac-91ef-bb3108f3e587</id> <link rel="alternate" href="https://blog.nsfisis.dev/posts/2024-02-10/yapcjapan-2024-report/"></link> diff --git a/services/nuldoc/public/blog/tags/yapc/index.html b/services/nuldoc/public/blog/tags/yapc/index.html index dba415d..4c07aad 100644 --- a/services/nuldoc/public/blog/tags/yapc/index.html +++ b/services/nuldoc/public/blog/tags/yapc/index.html @@ -45,6 +45,32 @@ <h1>タグ「YAPC」一覧</h1> </header> <article class="post-entry"> + <a href="/posts/2025-11-27/anybatross-writeup/"> + <header class="entry-header"> + <h2>カヤックさん開催のコードゴルフコンテスト Anybatross に参加して優勝した</h2> + </header> + <section class="entry-content"> + <p> + YAPC::Fukuoka 2025 に際してカヤックさんが開催されていたコードゴルフコンテスト、Anybatross に参加して優勝した。 + </p> + </section> + <footer class="entry-footer"> + <time datetime="2025-11-27">2025-11-27</time> 投稿 + <ul class="entry-tags"> + <li class="tag"> + Perl + </li> + <li class="tag"> + Ruby + </li> + <li class="tag"> + YAPC + </li> + </ul> + </footer> + </a> + </article> + <article class="post-entry"> <a href="/posts/2024-02-10/yapcjapan-2024-report/"> <header class="entry-header"> <h2>YAPC::Hiroshima 2024 参加レポ</h2> |
