Vim(Neovim)だけでAtCoderに参加したい


できたもの

ka-tsu-mo/at-vim-coder

最近AtCoderに参加し始めましたが、もっと過去問をといて本番でいいパフォーマンスを出せるように練習が必要だなと感じております。
ブラウザを開かずに使い慣れたVimのキーバインドだけで完結できるようなプラグインを目指しました。といってもやっていることはスクレイピングだけですが...

工夫したところ

AtCoderは問題文に数式が用いられていることがあります。このプラグインではなるべく見やすいように整えました。
\fracをスラッシュで置き換えるコードを紹介します。
下記関数にre.compile(r'\\frac\{.+\}')によって生成される正規表現オブジェクトsearchでマッチしたマッチオブジェクトを渡します。
Listのapendとpopのみを用いることでスタックのように振る舞います。

def _frac_to_slash(self, matchobj):
    text = matchobj.group(0)
    table = str.maketrans('{}', '()')
    for i in range(2):
        stack = []
        for j in range(len(text)):
            if text[j] == '{' or text[j] == '}':
                stack.append(j)
            if text[j] == '}':
                if len(stack) == 2 and text[stack[0]] == '{' and text[stack[1]] == '}':
                    break
                try:
                    stack.pop()
                    stack.pop()
                except:
                    return matchobj.group(0)
            if i == 0:
                try:
                    if len(text[stack[0]:stack[1]+1]) == 3:
                        numerator = text[stack[0]+1]
                    else:
                        numerator = text[stack[0]:stack[1]+1].translate(table)
                    text = text[stack[1]+1:]
                except:
                    return matchobj.group(0)
            if i == 1:
                try:
                    if len(text[stack[0]:stack[1]+1]) == 3:
                        denominator = text[stack[0]+1]
                    else:
                        denominator = text[stack[0]:stack[1]+1].translate(table)
                    return numerator + '/' + denominator + text[stack[1]+1:]
                except:
                    return matchobj.group(0)

例として、動画にも写っているABC145のC問題に使われている\fracを引用して紹介します。

\frac{\left(1+\sqrt{2}\right)+\left(1+\sqrt{2}\right)+\left(2\right)+\left(1+\sqrt{2}\right)+\left(2\right)+\left(1+\sqrt{2}\right)}{6}

このように中かっこの中に中かっこがあるので、正規表現だけではどうにもなりません。
上記ソースコードでは{または}が出現したらそのインデックスをスタックにつみ、}が出現した場合、対となるかっこと共にスタックから取り出します。上記の例を可視化すると(横に積み重なっていくイメージ)

[]
[5]
[5, 19]
[5, 19, 21]
[5]
[5, 43]
[5, 43, 45]
[5]
[5, 82]
[5, 82, 84]
[5]
[5, 121]
[5, 121, 123]
[5]
[5, 131]

こんな感じで分子部分が取り出せるので、もう一度同じ動作をして分母を取り出しスラッシュでくっつけると...

((1+√(2))+(1+√(2))+(2)+(1+√(2))+(2)+(1+√(2)))/6

こうなります。

見づらい!

絶対もっといい実装あるだろと思いつつ、他に思いつかないし\fracよりいいと思うのでこのまま使っています。
これも競プロ力の足りなさなんですかね。

まとめ

  • VimだけでAtCoderの問題に挑戦できるプラグインを作った。
  • pythonの単体テスト用のモジュール使えばよかった...。
  • 過去問の事ばかり考えていて、本番のコンテストに参加登録するコマンドを入れ忘れた(そのうち実装するはず)。
    • 試したことがないからわからないが、参加登録ボタンを押さなかった場合もコンテストの時間に問題文見れるんだろうか。
  • 過去問いっぱいといて強くなりたい。

プラグインに関して

  • 今のところ、C++とPython3とGoにしか対応してません。
    • Language Testの表のコマンドを全部試すのはしんどかったので...
    • 使いたい言語があればContributeしていただければと思います。
    • 新しいページが更新されたらこちらも更新していこうかと思っています。
  • 企業のコンテストは画像を使っている場合があるので、ブラウザで見た方がいいと思います。
  • WindowsのNeovimではテストしてないので、動くかわかりません。

参考にしたサイト