はじめに
この記事は, AtCoder 上の最短コードやリファレンスなどを読んで, ゴルフに役立ちそうなテクを自分なりにまとめたものです.
間違っている箇所や, ここに書いていないテクなどございましたら是非お気軽にコメントお願いします.
入力
- 入力全体を
$/で区切り,<>で 1 つずつ取得する(標準では"\n"が最後についている). - $a_1 \sqcup a_2 \sqcup \cdots \sqcup a_n$のような入力のとき
map{[$_での処理]},glob<>のようにする.glob<>で入力を空白でsplitし,mapをforのように用いて処理している.
- ある条件を満たす$a_i$の個数が欲しいときは,
grep{[$_での処理]},glob<>のようにする(ABC142-B).
- 文字列$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<>とする.
出力
配列
@a = (1, 2, 3); print @aとすると,1($,)2($,)3と出力される.@a = (1, 2, 3); print "@a"とすると,1($")2($")3と出力される.- 先頭要素のみ出力する場合は
printfを用いる(ABC098-A).
配列(@(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') |
文字列はマジカルインクリメントされる.
ソート
sort @_: ASCII コード順に昇順ソートされた配列が返る.sort {$a - $b} @_: 数値として昇順ソートされた配列が返る.sort {$a - $b} $x, $y, $z:$x, $y, $zを昇順ソートする.
特殊変数
| 変数 | 初期値 | 用途 | |||
|---|---|---|---|---|---|
$_ | undef | 様々な関数のデフォルト引数. | |||
$/ | "\n" | 入力時の区切り文字. $"や\1を渡すことが多い. | |||
$, | undef | 出力時の区切り文字. | |||
$" | " " | 配列を文字列化("@a")するときの区切り文字. | |||
$- | 0 | 代入すると非負整数に変換される. 0とのmaxを取りたいときに用いる. +=$-=のようにして最大値を更新できる. | |||
$. | undef | 入力を読み込んだ行数. | |||
$\ | undef | printした後にこの値が表示される. | |||
$% | 0 | 代入すると整数に変換される. | |||
| [`$ | `](http://perldoc.jp/variable/$%7C) | 0 | 代入すると整数に変換され, それが0でないなら1になる. `–$ | で0,1を切り替えるスイッチとして, $ | ++`で最初のみ処理を変えるために使える. |
特殊な初期値の変数
| 変数 | 初期値 | 用途 |
|---|---|---|
$^T (${chr(20)}) | - | プログラムを実行開始した時刻を, 紀元からの秒数として表したもの. |
$^F (${chr(6)}) | 2 | - |
$$ | AtCoder では4 | - |
$< | AtCoder では1000 | - |
$= | 60 | 代入すると整数に変換される. |
$; | chr(28) | - |
$: | "\n-" | - |
マッチング変数
どれも書き換え不可.
| 変数 | 初期値 | 用途 |
|---|---|---|
$` | undef | マッチした位置より前方の文字列. |
$& | undef | マッチした部分文字列. |
$' | undef | マッチした位置より後方の文字列. |
$1,$2,... | undef | n番目の()にマッチした部分文字列. |
その他変数
| 変数 | 初期値 | 用途 |
|---|---|---|
$a,$b | undef | sortでの比較関数で用いる. |
$#a | -1 | 配列@aの最終インデックスの値. pop@aする代わりに--$#aとした方が短い場合がある. |
演算子
上の方が優先順位が高い.
| 演算子 | 用途 | ||
|---|---|---|---|
++, -- | インクリメント, デクリメント. 前者は文字列に対しても適用できる(++($a="zz") #=> "aaa"). | ||
** | 指数演算子. | ||
!, ~ | 論理否定, bitwise の否定(1 の補数). | ||
+(単項) | print($a),$bのように, 関数名の直後に括弧があると(print($a)),$bとパースされるが, print+($a),$bとするとそれを回避できる. | ||
-(単項) | 数値ならば算術否定. 文字列ならば, それが数字(0~9,+,-)から始まってたらそれを数値化したものを算術否定, そうでないなら先頭に-を結合. | ||
=~, !~ | 左辺に対して右辺(/[パターン]/, s/[パターン]/[置換後]/, もしくは単に文字列)のパターンマッチを行う. | ||
*, /, %, x | 乗算, 除算, 剰余(右辺が負なら負), 文字列・配列の繰り返し. | ||
+, -, . | 加算, 減算, 文字列同士の連結. | ||
<<, >> | 左シフト, 右シフト. 左項は符号なし整数に変換され, 右項は$\mathrm{mod}\ 64$される(v5.24 以降では負の値を渡すと逆向きのシフトになる). | ||
<, >, <=, >= | 数値としての比較演算子. | ||
lt, gt, le, ge | 文字列としての比較演算子. | ||
==, !=, <=> | 数値としての等価演算子. <=>は右辺よりも左辺の方が小さい, 等しい, 大きいならば順に-1, 0, 1が返される. | ||
eq, ne, cmp | 文字列としての等価演算子. cmpは右辺よりも左辺の方が小さい, 等しい, 大きいならば順に-1, 0, 1が返される. | ||
& | bitwise の論理積. | ||
| ` | , ^` | bitwise の論理和, bitwise の排他的論理和. | |
&& | 短絡評価の論理積. ifの代わりに用いる. | ||
| ` | ` | 短絡評価の論理和. unlessの代わりに用いる. | |
.., ... | 範囲演算子. (start)..(end)は閉区間[start,end]のリストを返す. | ||
?, : | 三項演算子. 代入演算子よりも優先度が高いことに注意. | ||
=, +=, -=, … | 代入演算子. | ||
, | コンマ演算子. 常に右辺の値を返す. | ||
not | 優先順位の低い!. | ||
and | 優先順位の低い&&. | ||
or | 優先順位の低い` | `. | |
xor | 両側の式の排他的論理和. |
正規表現
標準では$_に対してパターンマッチが行われる. 特定の値に対して適用したい場合は, =~, !~を用いる.
- パターンとして空文字列を渡すと, 最後にマッチに成功したパターンが用いられる.
/[パターン]/[修飾子]- マッチしたら
true, マッチしなかったらfalseを返す. /の代わりに別の文字を用いたいときは,mを前置する.- 例.
m![パターン]!,m{[パターン]},m"[パターン]"
- 例.
- マッチしたら
s/[パターン]/[置換後]/[修飾子]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)となる./(?=(...))/g: 長さ 3 の連続部分文字列を全て取得 (yukicoder No.3068)$_="ABCDE"なら,ABC,BCD,CDE
関数
- 関数
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; }で囲う. |
ループ
$_に値が渡されるので, 正規表現や一部関数(absなど)と相性が良い.
- 後置
for:[$_での処理]for<> map:map{[$_での処理]}[配列],map[$_での処理],[配列]
その他
- バッククォートで囲まれた部分は, システムのコマンドとして実行される(
`dd`,`factor`など). - 小数部分を切り捨てたいときは
|0. 2 の累乗で割る場合は>>を用いるとさらに良い. $x-1は,~-$xとも書ける.undefは数値としては0, 文字列としては""(空文字列).