tcolorboxのカウンタを使って解答用紙の問題番号を振る

TeXで解答用紙を作るとき、問題番号は手で振りたくない。したがって何らかの形で自動化をするのが普通である。ここではtcolorboxのタイトルを使って番号を振ってみる。

次のような解答用紙を作ることを考える。

f:id:baruku07:20180202221137p:plain

問題番号の下には解答欄が入らないようにしたい。それをtcolorboxを使って実現する。以下が上を出力したソースであるある。

\documentclass[uplatex,dvipdfmx]{jsarticle}
\usepackage{tcolorbox}
\usepackage{enumitem}
\newcommand{\visible}{visible}
%
\newtcbox{\kasen}[1][]{boxrule=-1pt,bottomrule=1pt,sharp corners, colback=white,\visible,nobeforeafter,tcbox width=forced left,box align=base,\visible,#1}
%
\newtcolorbox[auto counter]{toi}{sidebyside, %横並びにする
lefthand width=1.6eM, %問題番号を入れる部分の幅。
sidebyside gap=0mm, %問題番号と解答部分の間隔を0にする。
sidebyside align = top,%
beforeafter skip =0mm, %問題と問題の箱の間隔を0にする。
upperbox=visible,lowerbox=visible, %\tcbsetでグローバルにinvisibleがセットされても良いようにしておく。
colframe=black,colback=white, %背景と線の色を白にする
detach title,title=\thetcbcounter,before upper ={\large \textsf{\tcbtitle}}, coltitle=black %タイトルを問題番号にする
}
%
\begin{document}
\begin{toi}
\tcblower
 \begin{enumerate}[align=left, leftmargin=*, label=(\arabic*)]
 \item \kasen{春は花粉症がしんどい。}
 \item \kasen{夏は暑いので夏バテがひどい。}
 \item \kasen{冬は寒いので動きたく無い。}
 \end{enumerate}
\end{toi}

\begin{toi}
\tcblower
(1) \kasen[width=3cm]{}
(2) \kasen[width=3cm]{}
(3) \kasen[width=3cm]{} \\
\noindent
(4) \kasen[width=3cm]{とら}
(5) \kasen[width=3cm]{}
(6) \kasen[width=3cm]{すずめ}
\end{toi}

\begin{toi}
\tcblower
\quad \par
\begin{tcolorbox}[height=6pc,colframe=white,colback=white,\visible]
$P(A)=0.4$, $P(A\cap B)=0.2$なので
\[
 P_{A}(B) = \frac{0.2}{0.4} = 0.5
\]
となる。
\end{tcolorbox}
\end{toi}
\end{document}

箱の枠を全て消しているので、何をやっているかがわかりにくい。そこで、上のコードでtoiのboxの箱の線を出力してみると(colframe=black)、何をやっているかがわかりやすい。

f:id:baruku07:20180202221521p:plain

このように、枠線を出力すると、レイアウトがどのような状態になっているかが一眼でわかる。これがtcolorboxで解答用紙を作るメリットの一つである。

tcolorboxで作っているので、右側の箱に何を書いても大丈夫という安心感もある。enumerate(や場合によってはtabular)で問題番号を振ると、この安心感はない。

説明は、だいたいコメントアウトしてある部分に買いてある通り。以下、補足。

  • 1の記述の線は以前の記事で買いた環境を使っている
  • 2の横並び箇条書きの部分は様々な解がある。ここではそれに触れたくなかったので手書きしている。
  • 問題番号の数字のフォントサイズを大きくしすぎると、右側とのバランスを取るのが難しくなる(これでも少しずれている)。これについては、もう少し何か考えないとならない。たとえば、sidebyside align = top seamとすると、今度は問題番号が上に上がりすぎてバランスが悪い。

1., 2.の小問の並びはtcolorboxの中にあるtcbitemizeを使えば、箇条書きと下線を同時にうまく捌けそうであるが、まだ使い方を理解していない。今後の課題である。

これまではどのようにしていたか

最初はenumerateを使っていた(普通)

箇条書き環境を使って問題番号を振るのが普通のアプローチである。私も最初はそうしていた。しかし、次のようなデメリットがある。

  • 問題に小問を付けると、箇条書きがネストするため扱いにくい。
  • 箇条書き環境であるがゆえの制約を意識するのが面倒(ソースに空行を入れると怒られるなど)。
  • ある問題でうっかりをしたとき、箇条書き全体に悪影響が及ぶことがあので怖い。(これで何度も時間を潰した)。
  • 細かい設定も含めて、問題ごとで色々な設定は完結させたい。箇条書き環境では、全体を意識せざるをえない。

これは、私の試験作成では致命的な欠点である。私は、試験問題の完成版を作って清書するという使い方で試験を作らない。問題を作れるときに作れるだけ作るというのを繰り返して試験を完成に持っていくスタイルで試験を作る。そのため、頻繁に問題の差し替えや並び替えなどもする。よって、問題単位で環境は閉じていてほしいという強い要求がある。

これまではtheorem環境を使っていた

この問題を解決するために、ある時期からは定理型の環境を使って問題番号を振るようにしていた。しかし、theorem環境はインラインな環境であるため、設定を工夫しないと番号の部分の直下にも文章が流し込まれる。これを防ぐために、パッケージを導入して、適当にパラメーターを触ってそうならないようにしていた。

しかし、theorem環境は滅多に触らないため、時が経つにつれパラメーターの意味が不明になってしまった。こうなる、触るのが面倒になりそれ以上は何もできない。

慣れているtcolorboxを使ってtheoremを置き換えることかできれば触りやすくなる。また、tcolorboxは機能が豊富なのであれこれやりやすそうである。これが、theorem環境で作っていた部分をtcolorboxに書き換えようとした動機である。