Help us understand the problem. What is going on with this article?

Perlゴルフの備忘録

More than 1 year has passed since last update.

はじめに

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

入力

  • 入力全体を$/で区切り, <>で1つずつ取得する(標準では"\n"が最後についている).
    • 入力がなければundefになる.
    • $/=$"(=' ')とすると, 空白区切りに入力を受け取れる. print$/=$",(..)のようにすると, print++を省けるケースもある(ABC083-A).
    • $/=\1のように, $/にスカラーへのリファレンスを渡すと, その文字数ずつ<>で読み込める(ABC078-A).
  • $a_1 \sqcup a_2 \sqcup \cdots \sqcup a_n$のような入力のとき
    • map{[$_での処理]},glob<>のようにする.
      • glob<>で入力を空白でsplitし, mapforのように用いて処理している.
    • ある条件を満たす$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<>とする.

配列(@(hoge))

  • @ai番目の要素を取り出すときは, $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')

文字列はマジカルインクリメントされる.

出力

  • @a = (1, 2, 3); print @aとすると, 1($,)2($,)3と出力される.
  • @a = (1, 2, 3); print "@a"とすると, 1($")2($")3と出力される.
  • 先頭要素のみ出力する場合はprintfを用いる(ABC098-A).

ソート

  • 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
前半4つは数値として, 後半4つは文字列としての比較演算子.
==, !=, <=>,
eq, ne, cmp
前半3つは数値として, 後半3つは文字列としての等価演算子.
<=>,cmpは右辺よりも左辺の方が小さい, 等しい, 大きいならば順に-1, 0, 1が返される.
& bitwiseの論理積.
|, ^ bitwiseの論理和, bitwiseの排他的論理和.
&& 短絡評価の論理積. ifの代わりに用いる.
|| 短絡評価の論理和. unlessの代わりに用いる.
.., ... 範囲演算子. (start)..(end)は閉区間[start,end]のリストを返す.
?: 三項演算子. 代入演算子よりも優先度が高いことに注意.
=, +=, -=, *=, ... 代入演算子.
, コンマ演算子. 常に右辺の値を返す.
not 優先順位の低い!.
and 優先順位の低い&&.
or 優先順位の低い ||.
xor 両側の式の排他的論理和.

正規表現

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

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

修飾子

修飾子 役割
i 大小文字の違いを無視する.
s /./が改行にもマッチするようにする.
m 複数行として扱う.
g 連続して何回もマッチする.
  • g : /pattern/gpatternに合致する要素を配列で取得できる.
    • @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自身の値

  • true1の値を持つ.
  • 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, 文字列としては""(空文字列).
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away