なぜ私はrepマクロを使っているのか
作成日:2017.09.23
カテゴリー:競プロに関するあれこれ
はじめに
競プロのマクロと聞いて真っ先に思い浮かぶであろうrepマクロであるが、使っている人は半数弱*のようである。
また使っている人の間でも細かい仕様は異なっていて、それぞれに意図があるものと思われる。
そこで本記事ではその意図の1つの紹介という意味で私自身がなぜrepマクロを使っているのかを記す。
* AGC019のB問題においてC++で解かれたコードを古いものから40個調べた結果、そのうちの16個でrepマクロが用いられていたことが分かった。
前提
この記事でいう「repマクロ」は「C++においてfor文をマクロ化したもの」を指す。
また私が使っているrepマクロは以下のものである。
#define repp(i,a,b) for(int i = (int)(a) ; i < (int)(b) ; ++i)
#define repm(i,a,b) for(int i = (int)(a) ; i > (int)(b) ; --i)
本題
使い始めたきっかけ
競プロの問題を解いている時に降順に処理することがあると思う。
その時、
for(int i = 0 ; i < N ; ++i)
という昇順に処理するコードではなく
for(int i = N-1 ; i >= 0 ; --i)
というコードを書かなければならない。
ところが昇順に処理するfor文の方をよく書くため、指が勝手に"--"ではなく"++"とタイプしてしまうことが時々起こる。
問題を解いている最中で、そこまで意識が回っていないために起こる誤りである。
ただ、間違えた場合には範囲外参照を起こすのでプログラムを動かした時に問題が生じる。
その問題というのが、ただプログラムが異常終了するというものだけなら大きな問題ではない。
しかしパソコン自体がフリーズしてしまうとなると大問題である。
私はその大問題を起こしたので同じ過ちを犯さないための方策を考えた結果、repマクロを使用するという結論に至ったのである。
こだわった点
先に記した様な経緯があるので、間違えて書いても範囲外参照を起こさないようにした。
諸悪の根源は不等号の向きとインクリメント・デクリメントが一致していないことであるから、それが起こらないようにしたということだ。
もちろんマクロを使っていて"repm"を"repp"と間違えて書くことも時々あるが、この時は何も起こらないようになっているので安全である。
また0から始まる昇順処理のfor文をを特別扱いして別のマクロを用意している人もいるが、私はタイプ量の削減を目的としていなかったので採用しなかった。
ただ、今使っているrepマクロでも副次的な効果としてかなりタイプ量が削減されているとは思う。
まとめ
for文内の不等号とインクリメント・デクリメントを合わせないことによってパソコンがフリーズする事態が起こった。
それを二度と起こさないようにするためにrepマクロを使っている。
また目的ではなかったが、タイプ量の削減がおまけとしてついてきた。