Perlゴルフの備忘録

## はじめに
この記事は, AtCoder上の最短コードやリファレンスなどを読んで, ゴルフに役立ちそうなテクを自分なりにまとめたものです.
間違っている箇所や, ここに書いていないテクなどございましたら是非お気軽にコメントお願いします.

## 入力

* 入力全体を`$/`で区切り, `<>`で1つずつ取得する(標準では`"\n"`が最後についている).
  * 入力がなければ`undef`になる.
  * `$/=$"(=' ')`とすると, 空白区切りに入力を受け取れる. `print$/=$",(..)`のようにすると, `print+`の`+`を省けるケースもある([ABC083-A](https://atcoder.jp/contests/abc083/submissions/1902695)).
  * `$/=\1`のように, `$/`にスカラーへのリファレンスを渡すと, その文字数ずつ`<>`で読み込める([ABC078-A](https://atcoder.jp/contests/abc078/submissions/1766103)).
* $a_1 \sqcup a_2 \sqcup \cdots \sqcup a_n$のような入力のとき
  * `map{[$_での処理]},glob<>`のようにする.
      * `glob<>`で入力を空白で`split`し, `map`を`for`のように用いて処理している.
  * ある条件を満たす$a_i$の個数が欲しいときは, `grep{[$_での処理]},glob<>`のようにする([ABC142-B](https://atcoder.jp/contests/abc142/submissions/7737435)).
* 文字列$S$を1文字ずつ処理したいとき, `[$_での処理]for<>=~/./g`とする.

### テンプレート

|                   入力                    |         コード         |                対応                |
| :---------------------------------------: | :--------------------: | :--------------------------------: |
|                $A\sqcup B$                |        `<>=~$"`        |          ``{A:$`, B:$'}``          |
|           $A \sqcup B \sqcup C$           |      `<>=~/ .* /`      |       ``{A:$`, B:$&, C:$'}``       |
|      $A \sqcup B \sqcup C \sqcup D$       |   `<>=~/ .* (.*) /`    |    ``{A:$`, B:$&, C:$1, D:$'}``    |
|  $A \sqcup B \sqcup C \sqcup D \sqcup E$  | `<>=~/ .* (.*) (.*) /` | ``{A:$`, B:$&, C:$1, D:$2, E:$'}`` |
|           $A \sqcup B \sqcup C$           |  `($a,$b,$c)=glob<>`   |        `{A:$a, B:$b, C:$c}`        |
| $a_1 \sqcup a_2 \sqcup \cdots \sqcup a_n$ |      `@a=glob<>`       |        配列`@a`に格納される        |

* `<>=~/[パターン]/`自身の値は, マッチしたら`true`, マッチしなかったら`false`となる.
  * ``print{hoge}for<>=~$"..$` ``とすることで``$` ``回ループが回せる.
  * 否定するには, `<>!~[hoge]`とすれば良い.
* 昇順ソートしたものを受け取りたいときは, `sort{$a-$b}glob<>`とする.

## 配列(`@(hoge)`)

* `@a`の`i`番目の要素を取り出すときは, `$a[i]`とする.
    * 最初の要素を用いて計算したいときは, `"@a"`を数値として用いれば良い.
        * `"1 2 3"`のような文字列を数値に変換すると`1`になるため.

* 要素数は, 数値化(`~~`, `*1`, ...)することで得られる.
    * `~~grep{hoge},fuga`のようにして, 条件`hoge`を満たす`fuga`内の要素数が求められる.

* 範囲演算子`..`

|         コード         |                 配列                  |
| :--------------------: | :-----------------------------------: |
|      `@a = 1..3`       |           `@a = (1, 2, 3)`            |
|  `@a = (1..3, 5..8)`   |     `@a = (1, 2, 3, 5, 6, 7, 8)`      |
| `@a = (1..3, 5, 7..9)` |     `@a = (1, 2, 3, 5, 7, 8, 9)`      |
|      `@a = e..i`       |   `@a = ('e', 'f', 'g', 'h', 'i')`    |
|     `@a = ay..bc`      | `@a = ('ay', 'az', 'ba', 'bb', 'bc')` |


  文字列は[マジカルインクリメント](http://perldoc.jp/docs/perl/5.8.8/perlop.pod#Auto-increment32and32Auto-decrement)される.

### 出力

* `@a = (1, 2, 3); print @a`とすると, `1($,)2($,)3`と出力される.
* `@a = (1, 2, 3); print "@a"`とすると, `1($")2($")3`と出力される.
* 先頭要素のみ出力する場合は`printf`を用いる([ABC098-A](https://atcoder.jp/contests/abc098/submissions/2571067)).

### ソート

* `sort @_` : **ASCIIコード**順に昇順ソートされた配列が返る.
* `sort {$a - $b} @_` : 数値として昇順ソートされた配列が返る.
* `sort {$a - $b} $x, $y, $z` : `$x, $y, $z`を昇順ソートする.

## [特殊変数](http://perldoc.jp/index/variable)

|                         変数                          |  初期値   |                             用途                             |
| :---------------------------------------------------: | :-------: | :----------------------------------------------------------: |
|         [`$_`](http://perldoc.jp/variable/$_)         |  `undef`  |                 様々な関数のデフォルト引数.                  |
|         [`$/`](http://perldoc.jp/variable/$/)         |  `"\n"`   |       入力時の区切り文字. `$"`や`\1`を渡すことが多い.        |
|         [`$,`](http://perldoc.jp/variable/$,)         |  `undef`  |                     出力時の区切り文字.                      |
|         [`$"`](http://perldoc.jp/variable/$")         |   `" "`   |         配列を文字列化(`"@a"`)するときの区切り文字.          |
|         [`$-`](http://perldoc.jp/variable/$-)         |    `0`    |   代入すると非負整数に変換される. `0`との`max`を取りたいときに用いる. `+=$-=`のようにして最大値を更新できる.  |
|         [`$.`](http://perldoc.jp/variable/$.)         |  `undef`  | 入力を読み込んだ行数. |
|         [`$\`](http://perldoc.jp/variable/$%5C)         |  `undef`  | `print`した後にこの値が表示される. |
|         [`$%`](http://perldoc.jp/variable/$%)         |    `0`    | 代入すると整数に変換される. |
|        [`$`&#124;](http://perldoc.jp/variable/$%7C)        |    `0`    | 代入すると整数に変換され, それが`0`でないなら`1`になる. <br> `--$`&#124;で`0`,`1`を切り替えるスイッチとして, `$`&#124;`++`で最初のみ処理を変えるために使える. |

### 特殊な初期値の変数

| 変数 | 初期値 | 用途 |
| :-: | :-: | :-: |
| [`$^T`<br>(`${chr(20)}`)](http://perldoc.jp/variable/$^T) |     -     | プログラムを実行開始した時刻を, 紀元からの秒数として表したもの. |
| [`$^F`<br>(`${chr(6)}`)](http://perldoc.jp/variable/$^F)  |    `2`    | - |
|         [`$$`](http://perldoc.jp/variable/$$)         |    AtCoderでは`4`    | - |
|         [`$<`](http://perldoc.jp/variable/$<)         |    AtCoderでは`1000`    | - |
|         [`$=`](http://perldoc.jp/variable/$=)         |   `60`    | 代入すると整数に変換される. |
|         [`$;`](http://perldoc.jp/variable/$;)         | `chr(28)` | - |
|         [`$:`](http://perldoc.jp/variable/$:)         |    `"\n-"`    | - |

### マッチング変数

どれも書き換え不可.

| 変数 | 初期値 | 用途 |
| :--: | :----: | :--: |
|       [``$` ``](http://perldoc.jp/variable/$`)        |  `undef`  | マッチした位置より前方の文字列. |
|         [`$&`](http://perldoc.jp/variable/$&)         |  `undef`  |    マッチした部分文字列.     |
|         [`$'`](http://perldoc.jp/variable/$')         |  `undef`  | マッチした位置より後方の文字列. |
|    [`$1`,`$2`,...](http://perldoc.jp/variable/$1)     |  `undef`  | `n`番目の`()`にマッチした部分文字列. |

### その他

|                    変数                     | 初期値  |                             用途                             |
| :-----------------------------------------: | :-----: | :----------------------------------------------------------: |
| [`$a`, `$b`](http://perldoc.jp/variable/$a) | `undef` |                 `sort`での比較関数で用いる.                  |
|                    `$#a`                    |  `-1`   | 配列`@a`の最終インデックスの値. <br> `pop@a`する代わりに`--$#a`とした方が短い場合がある. |

## [演算子](http://perldoc.jp/docs/perl/5.8.8/perlop.pod)

上の方が優先順位が高い.

|                    演算子                    |                             用途                             |
| :------------------------------------------: | :----------------------------------------------------------: |
|                  `++`, `--`                  | インクリメント, デクリメント. <br> 前者は文字列に対しても適用できる(`++($a="zz") #=> "aaa"`). |
|                     `**`                     |                         指数演算子.                          |
|                   `!`, `~`                   |              論理否定, bitwiseの否定(1の補数).               |
|                  `+`(単項)                   | `print($a),$b`のように, 関数名の直後に括弧があると`(print($a)),$b`とパースされるが, `print+($a),$b`とするとそれを回避できる. |
|                  `-`(単項)                   | 数値ならば算術否定. 文字列ならば, それが数字(`0~9,+,-`)から始まってたらそれを数値化したものを算術否定, そうでないなら先頭に`-`を結合. |
|                  `=~`, `!~`                  | 左辺に対して右辺(`/[パターン]/`, `s/[パターン]/[置換後]/`, もしくは単に文字列)のパターンマッチを行う. |
|              `*`, `/`, `%`, `x`              |  乗算, 除算, 剰余(右辺が負なら負), 文字列・配列の繰り返し.   |
|                `+`, `-`, `.`                 |                加算, 減算, 文字列同士の連結.                 |
|                  `<<`, `>>`                  |       左シフト, 右シフト. 左項は符号なし整数に変換され, 右項は$\mathrm{mod}\ 64$される(v5.24以降では負の値を渡すと逆向きのシフトになる).        |
| `<`, `>`, `<=`, `>=`, <br> `lt`, `gt`, `le`, `ge` |   前半4つは数値として, 後半4つは文字列としての比較演算子.    |
|     `==`, `!=`, `<=>`, <br> `eq`, `ne`, `cmp`     | 前半3つは数値として, 後半3つは文字列としての等価演算子. <br> `<=>`,`cmp`は右辺よりも左辺の方が小さい, 等しい, 大きいならば順に`-1`, `0`, `1`が返される. |
|                     `&`                      |                       bitwiseの論理積.                       |
|                   &#124;, `^`                   |           bitwiseの論理和, bitwiseの排他的論理和.            |
|                     `&&`                     |           短絡評価の論理積. `if`の代わりに用いる.            |
|                     &#124;&#124;                     |         短絡評価の論理和. `unless`の代わりに用いる.          |
|                 `..`, `...`                  | 範囲演算子. `(start)..(end)`は閉区間`[start,end]`のリストを返す. |
|                     `?:`                     |     三項演算子. 代入演算子よりも優先度が高いことに注意.      |
|          `=`, `+=`, `-=`, `*=`, ...          |                         代入演算子.                          |
|                     `,`                      |              コンマ演算子. 常に右辺の値を返す.               |
|                    `not`                     |                      優先順位の低い`!`.                      |
|                    `and`                     |                     優先順位の低い`&&`.                      |
|                 `or`                 |                   優先順位の低い &#124;&#124;.                  |
|                 `xor`                  |                   両側の式の排他的論理和.                   |

<!-- (※) もし`start,end`が条件(`/pattern/`など)で, 繰り返しなどで何度も評価される場合, `start`がON条件, `end`がOFF条件となるスイッチのように振る舞う. 内部状態がOFFのときは, `start`を満たしていればONにして`append`し, 直ちに`end`を評価して満たしていなければOFFにする. 内部状態がONのときは, `end`を評価して満たしていなければOFFにする. (`...`はほとんど`..`と変わらないが, 内部状態がOFFのときに`start`を満たしていた場合, `end`の評価はしない点が異なる. (つまりONになってすぐにはOFFにはならない.)) -->

## [正規表現](https://perldoc.jp/docs/perl/5.26.1/perlop.pod#Regexp32Quote-Like32Operators)

標準では`$_`に対してパターンマッチが行われる. 特定の値に対して適用したい場合は, `=~`, `!~`を用いる.

* パターンとして空文字列を渡すと, 最後にマッチに成功したパターンが用いられる.
* `/[パターン]/[修飾子]`
  * マッチしたら`true`, マッチしなかったら`false`を返す.
  * `/`の代わりに別の文字を用いたいときは, `m`を前置する.
    * 例. `m![パターン]!`, `m{[パターン]}`, `m"[パターン]"`
* `s/[パターン]/[置換後]/[修飾子]`
  * マッチした個数を返す (`g`を渡さなければ`0`か`1`).
  * 元の文字列を破壊する.
  * 置換後の文字には, マッチング変数が使える.
  * 特有の修飾子
      * `e` : Perlのコードとして評価する(`uc`, `lc`など)([ABC058-B](https://atcoder.jp/contests/abc058/submissions/4631748)).
      * `ee` : 文字列として評価したものを, Perlのコードとして評価する.
      * `r` : 元の文字列を破壊せずに, 置換後の文字列を返す([ABC064-A](https://atcoder.jp/contests/abc064/submissions/1339274)).
* `y/[パターンリスト]/[置換リスト]/[修飾子]`
  * パターンリストにマッチした文字数を返す.
    * 文字列内のある文字の数は, `y/[char]//`として得られる.
  * リストの要素を1つずつ対応するものに置換する.
    * `y/a-e/1-5/`なら, `a`を`1`, `b`を`2`, ..., `e`を`5`に置換する.
  * 特有の修飾子
      * `c` : パターンリストを補集合にする.
      * `d` : マッチはしたが, 置換リストに対応するものがないときに, その文字を削除する.
      * `s` : 置換後の文字が連続したとき, その文字を1文字に圧縮する(`($s="aabca")=~y/a-b/1/s #=> "1c1"`).
      * `r` : 元の文字列を破壊せずに, 置換後の文字列を返す.

## 修飾子

| 修飾子 |                 役割                 |
| :----: | :----------------------------------: |
|  `i`   |      大小文字の違いを無視する.       |
|  `s`   | `/./`が改行にもマッチするようにする. |
|  `m`   |          複数行として扱う.           |
|  `g`   |      連続して何回もマッチする.       |

* `g` : `/pattern/g`で`pattern`に合致する要素を配列で取得できる.
  *  `@a=/.(.)/g for<>;print "@a"`に`"abcdef"`を入力として与えると, `@a = (b, d, f)`となる.

## 関数

* 関数`f`を定義したいときは, `sub f{[処理]}`とする.
  * 関数内で最後に評価された値が返される(`sub f{1;2+3}`は`5`を返す).
* 引数は`@_`に格納される.
* 再帰したいときは, `&f`のようにリファレンスにする.

## 真偽値

未定義値`undef`, 空文字列`""`, 数値`0`, 文字列`"0"`, 空リスト`()`が`false`として評価され, その他は`true`となる.

### `true`, `false`自身の値

* `true`は`1`の値を持つ.
* `false`は`""`の値を持つが, 文字列としてのビット演算は行えず, `0`として数値のビット演算が行われる.
  * `"a" ^ "" #=> "a"`
  * `"a" ^ (1 < 0) #=> 0`
  * `"3" ^ (1 < 0) #=> 3`

## オプション
コードの先頭に`#!perl -[option]`と書くと, オプションに応じて以下のような効果が得られる.

| オプション | 効果 |
| :-: | :-: |
| `n` | コードを`while (<>) { [code] }`で囲う. |
| `p` | コードを`while (<>) { [code] print; }`で囲う. |

<!-- | `p` | 標準入力から1行読み込み, それを`$_`に格納する. <br> コードを一通り実行し, `$_`に格納されたものを出力する. <br> これを入力の終端まで行う. | -->

## ループ
`$_`に値が渡されるので, 正規表現や一部関数(`abs`など)と相性が良い.

* 後置`for` : `[$_での処理]for<>`
* `map` : `map{[$_での処理]}[配列]`, `map[$_での処理],[配列]`

## その他

* バッククォートで囲まれた部分は, システムのコマンドとして実行される(`` `dd` ``, `` `factor` ``など).
* 小数部分を切り捨てたいときは`|0`. 2の累乗で割る場合は`>>`を用いるとさらに良い.
* `$x-1`は, `~-$x`とも書ける.
* `undef`は数値としては`0`, 文字列としては`""`(空文字列).

<!-- * 空白区切りの数列の和 : `eval"+<>"x1e3`, `map(1..$_,glob<>)`

TODO
* グラフを貼るときのテンプレ : `push@$_,$_[--$|]for@_=glob`
* `substr(a,b,c)` : `a`のindex`b`から`c`文字とる.

-->