JupyterLabでatcoderやるときのinput問題

土曜日, 2月 13, 2021

Python

t f B! P L

JupyterLabでatcoderやるときのinput問題

input()が1行ずつしか入力できずテストケースの入力がめんどい。

私は以下のように対応しています。

ノートブックの先頭で一度だけ実行するコード。

def input():
    global tc
    if len(tc)>0:
        return tc.pop(0)

問題ごとに(というかコピペしたテストケースごとに)実行するコード

tc=!xsel --clipboard --output
print(tc)

説明

まずコード1でinput()メソッドを上書きする。
呼び出しごとにグローバル変数のリストtcの先頭要素を返すメソッドです。

これで、メインのコード(atcoderに提出するコード)には、そのままinput()と書くことができます。
コード1と下記のコード2は、atcoderには提出しないので、atcoder上では本来のinput()として認識されます。

tcは何でもいいですが、メインのコードで使わない変数名にします。

次にatcoderの問題ページでテストケースの入力例をコピーします。
「Copy」というボタンがあり、クリックするとコピーされるものでOKです。

コード2では、クリップボードの内容を変数tcに保存します。念の為、出力していますがこれは無くてもよいです。

xsel(Macだとpbpaste)はシェルコマンドですが、よく知られているように!マークに続けて書くとJupyter上でコマンドを実行できます。
さらにその出力を変数に保存でき、
さらにさらに改行があると自動でリストにしてくれるという親切っぷり。

動機

ググったけれども腑に落ちる解決策がなかった。

そんなに詳しく読んでないけど、メインコード側でinput()に相当するメソッド名を変える必要があったり(これだとデバッグ時と提出時でメソッド名を書き換える必要がある、まぁ別の行に書いてコメントアウトすればいいだけだけど)、全体的にトリッキーな方法が多かったので、Jupyterの標準機能だけでシンプルに解決したかった。

問題点

入力例ごとに毎回コピーする必要がある。
これはtcに入力例をPython上の文字列として代入すればセルに保存しておける。
これならxsel/pbpasteは不要。
私はどちらかというとxselのほうがやりやすかった。

あと、答え合わせはできない。
unittestモジュールを使って答え合わせまでしてくれるライブラリもあるので、そこまでやりたい人は素直にライブラリ使うのが良さそう。

QooQ