paiza×Qiitaキャンペーン Rubyでコードゴルフ【Dランク】

## はじめに
[paiza×Qiitaコラボキャンペーン](https://paiza.jp/pages/campaign/paiza-qiita) のDランク問題の[コードゴルフ](https://w.wiki/B2n2)にRubyで挑戦しました。
自分なりの解説も交えています。
恐らく最短ではないと思います。ですがせっかくの機会なので、自分の知見をまとめる目的で執筆しました。
さらに短くなるなどございましたら、コメントよろしくお願いいたします！

## N倍の文字列
https://paiza.jp/works/mondai/d_rank_skillcheck_archive/square
#### 問題概要
標準入力で与えられた整数個`*`を繋げた文字列を出力してください。
#### Rubyコードゴルフ解答（16文字）
```ruby
$><<?**gets.to_i
```
#### 解説
上記の解答を分かりやすく書くと、以下のようになります。
```ruby
puts "*"*gets.to_i
```
文字`*`を標準入力で得た回数だけ連結した文字列を標準出力しています。
ここから2箇所短くする余地があります。
1. `"*"`の部分です。文字列が1文字の場合に限り、[Rubyの文字リテラル](https://docs.ruby-lang.org/ja/latest/doc/spec=2fliteral.html#char)が利用できます。そのため`"*"`は`?*`と置き換えられます。
2. `puts`の部分です。Rubyでは[特殊変数`$>`](https://docs.ruby-lang.org/ja/latest/class/Kernel.html#V_--3E)が`puts`や`p`のデフォルト出力先になっています。その特殊変数`$>`に文字列を流し込むイメージで、`$><<`と表現できます。
恩恵として`puts`直後に必要だった半角スペースが削除できます。以下のようになります。
    ```ruby
    puts "Hello"
    $><<"Hello" #good
    ```

## Eメールアドレス
https://paiza.jp/works/mondai/d_rank_skillcheck_archive/email_address
#### 問題概要
2行で与えられる文字列を、`@`を間に挟んで連結してください。
#### Rubyコードゴルフ解答（17文字）
```ruby
$><<`dd`.split*?@
```
#### 解説
ポイントは3箇所です。
1. `` `dd` ``の部分です。標準入力2行の受け取りを1度で済ませます。Rubyでは[バッククオートで外部コマンドを利用できます](https://docs.ruby-lang.org/ja/latest/method/Kernel/m/=60.html)。`` `dd` ``とすると、全行を一気に文字列として読み込むことができます。
確認のため入力例1で`` `dd` ``で受け取ったものを確認すると、`"paiza\nexample.com\n"`という、改行記号`\n`も混在した1つの文字列となっています。
2. ``.split``の部分です。1.で受け取った文字列`"paiza\nexample.com\n"`を加工します。
まずは、改行記号で文字列を分割します。[String#split](https://docs.ruby-lang.org/ja/latest/method/String/i/split.html)が便利です。改行された結果が配列`["paiza", "example.com"]`となります。
3. `*?@`の部分です。配列`["paiza", "example.com"]`の各要素を[Array#*](https://docs.ruby-lang.org/ja/latest/method/Array/i/=2a.html)で結合することができます。以下が使用例です。結合する文字列には、先ほどの文字リテラルを用いて、`"@"`ではなく`?@`として1文字削除しています。
    ```ruby
    p ["A","B","C"]*"X" #=> "AXBXC"
    p [1,2,3]*"X" #=> "1X2X3" 配列の要素が文字列以外の時、文字列への型変換が試されます
    ```

## 足し算
https://paiza.jp/works/mondai/d_rank_skillcheck_sample/addition
#### 問題概要
空白区切りで与えられる2つの整数の和を出力してください。
#### Rubyコードゴルフ解答（16文字）
```ruby
p eval`tr ' ' +`
```
#### 解説
ポイントは3箇所です。
1. `eval`の部分です。今回の全体方針としては、与えられた文字列を足し算の式の形の文字列に加工して、`eval`で実行しています。[Kernel.#eval](https://docs.ruby-lang.org/ja/latest/method/Kernel/m/eval.html)が利用できます。これは与えられた文字列をRubyプログラムとして実行します。例えば以下のようになります。
    ```ruby
    p eval("1+3") #=> 4
    eval("3.times{puts 'Hello'}") #=> Helloが3行出力される
    ```

2. `` `tr ' ' +` ``の部分です。先ほど述べたように、`eval`で実行される文字列を作ります。目標は、例えば入力が`"1 1"`のとき、`"1+1"`という文字列にしたいです。
これは間に存在する半角スペースを`"+"`という文字列に置換すればよいです。これは、先ほど紹介した外部コマンドを利用する方法で、`tr`を用いればよいです。`tr`コマンドで入力を受け取りながら、半角スペースを`"+"`に置換しています。
3. 実は`` eval(`tr ' ' +` ) ``としなくても`` eval`tr ' ' +` ``で動きます。Rubyでは多くの箇所で引数の括弧を省略でき、`eval`直後の半角スペースも今回は省略しても正しく認識してくれます。

## 一番小さい値
https://paiza.jp/works/mondai/d_rank_skillcheck_sample/min_num
#### 問題概要
5行の各整数のうち最小値を出力してください。
#### Rubyコードゴルフ解答（22文字）
```ruby
puts`sort -n`.split[0]
```
#### 解説
外部コマンド`` `sort -n` ``を使用しています。全行を数値として解釈してソートしています。ソートした結果の文字列は、入力例1ですと`"4\n8\n10\n12\n46\n"`となっています。
この文字列の最初の`\n`の直前までが欲しいので、`split`してできた配列`["4", "8", "10", "12", "46"]`の最初の要素を`[0]`で取り出します。


## 文字列の一致
https://paiza.jp/works/mondai/d_rank_skillcheck_sample/diff_str
#### 問題概要
2行の各文字列が、一致しているか判定してください
#### Rubyコードゴルフ解答（28文字）
```ruby
puts gets==gets+?\n?:OK: :NG
puts gets==gets ? :OK: :NG #本来ならこれで…
```
#### 解説
1行ずつそれぞれ`gets`で受け取り、素直に比較する方針です。
もう1箇所ポイントは、3項演算子の時の文字列出力の書き方です。出力する文字列をシンボルとしても、`puts`の際に文字列に変換されます。以下が短縮の流れです。
```ruby
puts gets==gets ? "OK" : "NG"
puts gets==gets ? :OK : :NG #文字列をシンボルに変更
puts gets==gets ? :OK: :NG #OKの直後のスペースは削除可能
puts gets==gets?:OK: :NG #gets?というメソッドが無いためこれは不可。
```
本来ならこれで良いはずなのですが、ジャッジケースの不備？のため、末尾に改行が入っておらず、`+?\n`で対処しています。またこれに伴い`?`前後のスペースも削除できました。

## おわりに
実は今回Qiita初投稿で、執筆しながら、記事にするというのはとても難しいと感じました。
いつもQiitaの投稿に大変お世話になっています。
投稿者の皆様、いつも素晴らしい記事をありがとうございます！