python と LaTeX で100マス計算プリント用texファイルを自動生成できるようにしてみた
小学生に100マス計算させたい!ネットに色々転がってるけど、かゆいところに手が届かない。細かく難度調整できるようにしつつ大量にプリント生成したい……
というわけで初心者ですが、プログラムの勉強がてら作ってみました。
無駄だらけのコードだと思いますが、生温かい目で見てください
?「Python からLaTeX経由してPDF生成するより、htmlベースで書いて直接PythonでPDF生成した方が早いじゃん。」
いやほんと、そうですよね。完成した後に気づきました。
環境
・Python: Google Colab
・LaTeX: Windowsに適当にインストール
Pythonは個人PCにも入れているのですが、Google Colabだとどこからでもアクセスできるので便利かなと思ってこちらにしました。
コードも files のところとかが多少Google Colab用になってますが、大体普通のpython と同じでよかったです。
工程
LaTeXで基礎を作る
Pythonで100マス計算のランダム生成および texファイルへの落とし込みができるようにする
とざっくりこんな感じです。
1. LaTeXで基礎を作る
LaTeXで作った基礎はこんな感じ。一ページで2問の100マス計算。解答も別ページに印刷します。
python に転写する作業がめんどくさいので極力シンプルに。


\documentclass[10pt,a4j]{jsarticle}
\usepackage{array}
\pagestyle{empty}
\setlength{\headheight}{0pt}
\setlength{\marginparwidth}{0pt}
\begin{document}
\underline{\Large 百マス計算 No.x}\\
\vspace{1\baselineskip}
\renewcommand{\arraystretch}{1.4}
\begin{center}
\begin{tabular}{|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.3cm} wc{2.5cm}} \cline{1-11}
+ & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 \\ \cline{1-11}
1 & & & & & & & & & & \\ \cline{1-11}
2 & & & & & & & & & & & & \hfill 月~~~~~~~日 \\ \cline{1-11} \cline{13-13}
3 & & & & & & & & & & \\ \cline{1-11}
4 & & & & & & & & & & \\ \cline{1-11}
5 & & & & & & & & & & \\ \cline{1-11}
6 & & & & & & & & & & & & \hfill 分~~~~~~~秒 \\ \cline{1-11} \cline{13-13}
7 & & & & & & & & & & \\ \cline{1-11}
8 & & & & & & & & & & \\ \cline{1-11}
9 & & & & & & & & & & \\ \cline{1-11}
10 & & & & & & & & & & & & \hfill 点 \\ \cline{1-11} \cline{13-13}
\end{tabular} \\
\vspace{2.5\baselineskip}
\begin{tabular}{|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.3cm} wc{2.5cm}} \cline{1-11}
+ & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 \\ \cline{1-11}
1 & & & & & & & & & & \\ \cline{1-11}
2 & & & & & & & & & & \\ \cline{1-11}
3 & & & & & & & & & & \\ \cline{1-11}
4 & & & & & & & & & & \\ \cline{1-11}
5 & & & & & & & & & & \\ \cline{1-11}
6 & & & & & & & & & & & & \hfill 分~~~~~~~秒 \\ \cline{1-11} \cline{13-13}
7 & & & & & & & & & & \\ \cline{1-11}
8 & & & & & & & & & & \\ \cline{1-11}
9 & & & & & & & & & & \\ \cline{1-11}
10 & & & & & & & & & & & & \hfill 点 \\ \cline{1-11} \cline{13-13}
\end{tabular}
\end{center}
\newpage
\underline{\Large 百マス計算 No.x 解答}\\
\vspace{1\baselineskip}
\renewcommand{\arraystretch}{1.4}
\begin{center}
\begin{tabular}{|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|} \hline
+ & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 \\ \hline
1 & & & & & & & & & & \\ \hline
2 & & & & & & & & & & \\ \hline
3 & & & & & & & & & & \\ \hline
4 & & & & & & & & & & \\ \hline
5 & & & & & & & & & & \\ \hline
6 & & & & & & & & & & \\ \hline
7 & & & & & & & & & & \\ \hline
8 & & & & & & & & & & \\ \hline
9 & & & & & & & & & & \\ \hline
10 & & & & & & & & & & \\ \hline
\end{tabular} \\
\vspace{2.5\baselineskip}
\begin{tabular}{|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|} \hline
+ & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 \\ \hline
1 & & & & & & & & & & \\ \hline
2 & & & & & & & & & & \\ \hline
3 & & & & & & & & & & \\ \hline
4 & & & & & & & & & & \\ \hline
5 & & & & & & & & & & \\ \hline
6 & & & & & & & & & & \\ \hline
7 & & & & & & & & & & \\ \hline
8 & & & & & & & & & & \\ \hline
9 & & & & & & & & & & \\ \hline
10 & & & & & & & & & & \\ \hline
\end{tabular}
\end{center}
\newpage
\end{document}
2. Python に落とし込み
やっぱり思ったより時間かかっちゃいました。
個人的に学び/過去の知識を思い出すきっかけになったのは以下の3つでした
1. int と str が混ざったリストを一文にまとめるときは format関数を使う
2. copy は 浅いコピーと深いコピーを使い分ける
3. python は "\" の扱いがめんどくさいので、これを含む要素は直前にrを置いたりして対処する
完成
完成したプログラムは最後に置きます。
ポイントは
・難度調整を細かくできるようにしたこと(好きな数字の範囲で出題できる)
・プリントページ数を自由に変えられるようにしたこと
・プリントに自由にナンバーを振れるようにしたこと
あたりです。
桁数が大きくなっちゃうと枠の幅が足りなくなっちゃうけど、まぁそんなレベルまでつくらないからいいか。
ちょこちょこっと学んだ過去の知識を掘り起こしながら作成できて結構楽しかったです。
以上、備忘録まで。
! rm "/content/mas.tex"
import random
import copy
from google.colab import files
# ----- control ------
num_page = 15
start_No = 26
mylist = list(range(1,11)) # range(a,b): a 以上 b 未満の範囲の数字で100マス計算を生成。ここで難度調整する。
# ----- def ------
texbase = [
r'\documentclass[10pt,a4j]{jsarticle}', #0
r'\usepackage{array}', #1
r'\pagestyle{empty}', #2
r'\setlength{\headheight}{0pt}', #3
r'\setlength{\marginparwidth}{0pt}', #4
r'\begin{document}', #5
r'\renewcommand{\arraystretch}{1.4}', #6
r'\underline{\Large 百マス計算 No.x}\\', #7
r'\vspace{1\baselineskip}', #8
r'\begin{center}', #9
r'\begin{tabular}{|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.3cm} wc{2.5cm}} \cline{1-11}', #10
r'+ & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 \\ \cline{1-11}', #11
r'1 & & & & & & & & & & \\ \cline{1-11}', #12
r'2 & & & & & & & & & & & & \hfill 月~~~~~~~日 \\ \cline{1-11} \cline{13-13}', #13
r'3 & & & & & & & & & & \\ \cline{1-11}', #14
r'4 & & & & & & & & & & \\ \cline{1-11}', #15
r'5 & & & & & & & & & & \\ \cline{1-11}', #16
r'6 & & & & & & & & & & & & \hfill 分~~~~~~~秒 \\ \cline{1-11} \cline{13-13}', #17
r'7 & & & & & & & & & & \\ \cline{1-11}', #18
r'8 & & & & & & & & & & \\ \cline{1-11}', #19
r'9 & & & & & & & & & & \\ \cline{1-11}', #20
r'10 & & & & & & & & & & & & \hfill 点 \\ \cline{1-11} \cline{13-13}', #21
r'\end{tabular} \\', #22
r'\vspace{2.5\baselineskip}', #23
r'\begin{tabular}{|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.3cm} wc{2.5cm}} \cline{1-11}', #24
r'+ & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 \\ \cline{1-11}', #25
r'1 & & & & & & & & & & \\ \cline{1-11}', #26
r'2 & & & & & & & & & & \\ \cline{1-11}', #27
r'3 & & & & & & & & & & \\ \cline{1-11}', #28
r'4 & & & & & & & & & & \\ \cline{1-11}', #29
r'5 & & & & & & & & & & \\ \cline{1-11}', #30
r'6 & & & & & & & & & & & & \hfill 分~~~~~~~秒 \\ \cline{1-11} \cline{13-13}', #31
r'7 & & & & & & & & & & \\ \cline{1-11}', #32
r'8 & & & & & & & & & & \\ \cline{1-11}', #33
r'9 & & & & & & & & & & \\ \cline{1-11}', #34
r'10 & & & & & & & & & & & & \hfill 点 \\ \cline{1-11} \cline{13-13}', #35
r'\end{tabular} ', #36
r'\end{center}', #37
r'\newpage', #38
r'\underline{\Large 百マス計算 No.x 解答}\\', #39
r'\vspace{1\baselineskip}', #40
r'\begin{center}', #41
r'\begin{tabular}{|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|} \hline', #42
r'+ & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 \\ \hline', #43
r'1 & & & & & & & & & & \\ \hline', #44
r'2 & & & & & & & & & & \\ \hline', #45
r'3 & & & & & & & & & & \\ \hline', #46
r'4 & & & & & & & & & & \\ \hline', #47
r'5 & & & & & & & & & & \\ \hline', #48
r'6 & & & & & & & & & & \\ \hline', #49
r'7 & & & & & & & & & & \\ \hline', #50
r'8 & & & & & & & & & & \\ \hline', #51
r'9 & & & & & & & & & & \\ \hline', #52
r'10 & & & & & & & & & & \\ \hline', #53
r'\end{tabular} \\', #54
r'\vspace{2.5\baselineskip}', #55
r'\begin{tabular}{|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|wc{0.6cm}|} \hline', #56
r'+ & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 \\ \hline', #57
r'1 & & & & & & & & & & \\ \hline', #58
r'2 & & & & & & & & & & \\ \hline', #59
r'3 & & & & & & & & & & \\ \hline', #60
r'4 & & & & & & & & & & \\ \hline', #61
r'5 & & & & & & & & & & \\ \hline', #62
r'6 & & & & & & & & & & \\ \hline', #63
r'7 & & & & & & & & & & \\ \hline', #64
r'8 & & & & & & & & & & \\ \hline', #65
r'9 & & & & & & & & & & \\ \hline', #66
r'10 & & & & & & & & & & \\ \hline', #67
r'\end{tabular}', #68
r'\end{center}', #69
r'\newpage', #70
r'\end{document}', #71
]
def mas_gen(l):
# 10個の数字を入れたリストを突っ込むとQ, Aの二つのリストをくっつけた形でreturnする
tate = random.sample(l,10)
yoko = random.sample(l,10)
masQ = []
masQ.append(yoko)
masQ[0].insert(0,'+')
for i in range(10):
masQ.append([tate[i],'','','','','','','','','',''])
masA = []
masA.append(yoko)
for i in range(10):
add = [tate[i]]
for j in range(1,11):
add.append(tate[i]+yoko[j])
masA.append(add)
return masQ, masA
def array_trans_Q1(l):
a = []
for i in range(len(l)):
tmp = l[i][0]
for j in range(1,len(l[i])):
tmp = '{} & {}'.format(tmp, l[i][j])
if i == 2:
tmp = '{}{}'.format(tmp,r' & & \hfill 月~~~~~~~日 \\ \cline{1-11} \cline{13-13}')
a.append(tmp)
elif i == 6:
tmp = '{}{}'.format(tmp,r' & & \hfill 分~~~~~~~秒 \\ \cline{1-11} \cline{13-13}')
a.append(tmp)
elif i == 10:
tmp = '{}{}'.format(tmp,r' & & \hfill 点 \\ \cline{1-11} \cline{13-13}')
a.append(tmp)
else:
tmp = '{}{}'.format(tmp,r' \\ \cline{1-11}')
a.append(tmp)
return a
def array_trans_Q2(l):
a = []
for i in range(len(l)):
tmp = l[i][0]
for j in range(1,len(l[i])):
tmp = '{} & {}'.format(tmp, l[i][j])
if i == 6:
tmp = '{}{}'.format(tmp,r' & & \hfill 分~~~~~~~秒 \\ \cline{1-11} \cline{13-13}')
a.append(tmp)
elif i == 10:
tmp = '{}{}'.format(tmp,r' & & \hfill 点 \\ \cline{1-11} \cline{13-13}')
a.append(tmp)
else:
tmp = '{}{}'.format(tmp,r' \\ \cline{1-11}')
a.append(tmp)
return a
def array_trans_A(l):
a = []
for i in range(len(l)):
tmp = l[i][0]
for j in range(1,len(l[i])):
tmp = '{} & {}'.format(tmp, l[i][j])
tmp = '{}{}'.format(tmp,r' \\ \hline')
a.append(tmp)
return a
def mas_prepare(n):
page = []
for i in range(n):
N1 = []
N2 = []
mas1 = mas_gen(mylist)
Q1 = array_trans_Q1(mas1[0])
A1 = array_trans_A(mas1[1])
N1.append(Q1), N1.append(A1)
mas2 = mas_gen(mylist)
Q2 = array_trans_Q2(mas2[0])
A2 = array_trans_A(mas2[1])
N2.append(Q2), N2.append(A2)
page.append(N1), page.append(N2)
return page
def page_translator(l_page):
tex_writer= copy.deepcopy(texbase)
del tex_writer[7:71]
for i in range(len(l_page)//2):
tex_content = copy.deepcopy(texbase)
tex_content[7] = '{}{}{}'.format(r'\underline{\Large 百マス計算 No.', start_No + i ,r'}\\')
tex_content[39] = '{}{}{}'.format(r'\underline{\Large 百マス計算 No.', start_No + i ,r' 解答}\\')
for j in range(11,22):
tex_content[j] = l_page[i][0][j-11]
for k in range(25,36):
tex_content[k] = l_page[i+1][0][k-25]
for m in range(43,54):
tex_content[m] = l_page[i][1][m-43]
for n in range(57,68):
tex_content[n] = l_page[i+1][1][n-57]
#
tmp = copy.deepcopy(tex_content[7:71])
for o in range(len(tmp)):
tex_writer.insert(-1,tmp[o])
return tex_writer
# ----- main ------
test = mas_prepare(num_page)
filecontent = page_translator(test)
cont = filecontent[0]
for i in range(1,len(filecontent)):
cont = '{}\n{}'.format(cont,filecontent[i])
with open('mas.tex','w') as x:
print(cont,file=x)
files.download('mas.tex')