はじめに
この記事は, 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 | 代入すると整数に変換される. |
$| | 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
, 文字列としては""
(空文字列).