pythonで計算問題をつくる
小学校が休校になって一ヶ月以上になる
自宅学習をさせているけど
計算問題をこなす数が足りない気がしたので
pythonの勉強も兼ねてiPadのpythonisata3を使って
ランダムに計算問題を作るスクリプトを書いた
出力したいのは
- 2-3桁の掛け算
- あまりのある割り算
- 少数の足し算・引き算
- 分数の足し算・引き算
方針は2つの数について計算して
表示する数式を出力する関数を作る
実際の計算はノートにやってもらって
答え合わせのときに答えを出力させる
イメージはこんな感じ
計算の種類を選んで数字を入力してね 1: 少数のたし算・ひき算 2: 大きな数のかけ算 3: あまりのあるわり算 4: 分数のたし算・ひき算 数値を入力 (1 - 4): 1 1) 94.8 + 84.1 = ? 2) 37.0 + 19.1 = ? 3) 96.1 + 21.9 = ? 終わったらendを入力してね>>end 1) 94.8 + 84.1 = 178.9 2) 37.0 + 19.1 = 56.1 3) 96.1 + 21.9 = 118.0
操作と表示の流れは
- どの計算をするか選んで数字を入力
- 数式の表示
- 手書きで計算が終わったらendを入力
- 答えの表示
となる
問題は分数の表示
アスキーアートみたいに表示はできなくはないけど
できればTeXを使いたい
こんな感じ
調べてみたら
matplotlibを使えば文字をLaTeX表示できるらしい
http://civilyarou.web.fc2.com/Tech_etc/sub_j_latex_test.html
グラフの軸を消してタイル表示させれば
等間隔に数式を並べられる
matplotlibでAxesを真っ白にする(x軸とかy軸なんかを消して非表示にする) - 静かなる名辞
matplotlibのめっちゃまとめ - Qiita
初めてclassを自作した
この本を参考にした
ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装
(Amazonに飛びます)
classには数式を作るメソッドを定義した
数式を作るときに計算の答えも計算してあって
問題の式、答えを含む式の2つを作る
PythonistaではTeXのコマンドが使える程度っぽい
表示はあまりきれいでない
デスクトップでTeX表示する場合は
rc('text', usetex=True)
を使うと表示がきれいになる
実際のコードはこちら
libraryのconsoleはPythonisata3のライブラリなので
デスクトップで実行する場合は削除する
math_exam.py
import console import matplotlib.pyplot as plt from matplotlib.ticker import * from matplotlib import rc import random import numpy as np from math_class import math_equations #rc('text', usetex=True) console.clear() console.set_font('Menlo',20) math = math_equations() x = 3 y = 2 n = x * y print('計算の種類を選んで数字を入力してね') print('1: 少数のたし算・ひき算') print('2: 大きな数のかけ算') print('3: あまりのあるわり算') print('4: 分数のたし算・ひき算') while True: eq_type = input('数値を入力 (1 - 4): ') if eq_type > '0' and eq_type < '5': break ans = [] if eq_type == '1': for j in range(0, int(n/2)): r = np.array(math.generate_decimal(n, 2, 2, 1)) r[0][j], r[1][j] = math.replace_num(r[0][j], r[1][j]) tmp = math.eq_summation(r[0][j], r[1][j]) ans.append(tmp[1]) print(str(j + 1) + ') ' + tmp[0]) if (j + 1) % 5 == 0: print() for j in range(int(n/2), n): r = np.array(math.generate_decimal(n, 2, 2, 1)) r[0][j], r[1][j] = math.replace_num(r[0][j], r[1][j]) tmp = math.eq_subtraction(r[0][j], r[1][j]) ans.append(tmp[1]) print(str(j + 1) + ') ' + tmp[0]) if (j + 1) % 5 == 0: print() elif eq_type == '2': for j in range(n): r = np.array(math.generate_int(n, 2, 2, 1)) r[0][j], r[1][j] = math.replace_num(r[0][j], r[1][j]) tmp = math.eq_multiplication(r[0][j], r[1][j]) ans.append(tmp[1]) print(str(j) + ') ' + tmp[0]) if (j + 1) % 5 == 0: print() elif eq_type == '3': for j in range(n): r = np.array(math.generate_int(n, 1, 2, 1)) r[0][j], r[1][j] = math.replace_num(r[0][j], r[1][j]) r[0][j] = random.randrange(r[1][j],10 * r[1][j]) tmp = math.eq_division(r[0][j], r[1][j]) ans.append(tmp[1]) print(str(j) + ') ' + tmp[0]) if (j + 1) % 5 == 0: print() elif eq_type == '4': fig, axes = plt.subplots(x, y) m = 0 for i in range(x): for j in range(0, int(y/2)): r = np.array(math.generate_int(n, 2, 2, 1)) r[0][j], r[1][j] = math.replace_num(r[0][j], r[1][j]) tmp = math.eq_fraction_sum(r[0][j], r[1][j], r[2][j]) ans.append(tmp[1]) axes[i, j].axis('off') axes[i, j].text(0.0, 0.5, str(m + 1) + ') ' + tmp[0], fontsize = 20) m += 1 for j in range(int(y/2), y): r = np.array(math.generate_int(n, 2, 2, 1)) r[0][j], r[1][j] = math.replace_num(r[0][j], r[1][j]) tmp = math.eq_fraction_sub(r[0][j], r[1][j], r[2][j]) ans.append(tmp[1]) axes[i, j].axis('off') axes[i, j].text(0.0, 0.5, str(m + 1) + ') ' + tmp[0], fontsize = 20) m += 1 plt.show() print() while True: inp=input('終わったらendを入力してね>>') print() if inp == 'end': break if eq_type != '4': for i in range(n): print(str(i + 1) + ') ' + ans[i]) if (i + 1) % 5 == 0: print() else: fig, axes = plt.subplots(x, y) m = 0 for i in range(x): for j in range(y): axes[i, j].axis('off') axes[i, j].text(0.0, 0.5, str(m + 1) + ') ' +ans[m], fontsize = 20) m += 1 plt.show()
math_class.py
import random class math_equations: def __init__(self): pass def eq_summation(self, a, b): re = a + b eq = str(a) + ' + ' + str(b) + ' = ' return eq + '?', eq + str(re) def eq_subtraction(self, a, b): re = a - b eq = str(a) + ' - ' + str(b) + ' = ' return eq + '?', eq + str(re) def eq_multiplication(self, a, b): re = a * b eq = str(a) + ' × ' + str(b) + ' = ' return eq + '?', eq + str(re) def eq_division(self, a, b): re = a // b su = a % b eq = str(a) + ' ÷ ' + str(b) + ' = ' return eq + '?', eq + str(re) + '・・・' + str(su) def eq_fraction_sum(self, a, b, c): re = a + b if a != c and b != c: eq = r'$\frac{' + str(a) + '}{' + str(c) + '} + \\frac{' + str(b) + '}{' + str(c) + '} = ' elif a == c: eq = r'$1 + \frac{' + str(b) + '}{' + str(c) + '} = ' elif b == c: eq = r'$\frac{' + str(a) + '}{' + str(c) + '} + 1 = ' return eq + '?$', eq + '\\frac{' + str(re) + '}{' + str(c) + '}$' def eq_fraction_sub(self, a, b, c): re = a - b if a != c and b != c: eq = r'$\frac{' + str(a) + '}{' + str(c) + '} - \\frac{' + str(b) + '}{' + str(c) + '} = ' elif a == c: eq = r'$1 - \frac{' + str(b) + '}{' + str(c) + '} = ' elif b == c: eq = r'$\frac{' + str(a) + '}{' + str(c) + '} - 1 = ' return eq + '?$', eq + '\\frac{' + str(re) + '}{' + str(c) + '}$' def replace_num(self, a, b): if a < b: tmp = a a = b b = tmp return a, b def generate_int(self, n, dim_x, dim_y, dim_z): a = [] b = [] c = [] for i in range(n): a.append(random.randrange(10 ** (dim_x - 1), 10 ** dim_x)) b.append(random.randrange(10 ** (dim_y - 1), 10 ** dim_y)) c.append(random.randrange(2, 99)) return a, b, c def generate_decimal(self, n, dim_x, dim_y, dim_z): a = [] b = [] c = [] for i in range(n): a.append(round(random.uniform(10 ** (dim_x - 1), 10 ** dim_x), 1)) b.append(round(random.uniform(10 ** (dim_y - 1), 10 ** dim_y), 1)) c.append(round(random.uniform(10 ** (dim_z - 1), 10 ** dim_z), 1)) return a, b, c
実際に触らせてみたら
数字を選ぶところで
画面を触ってた。。。。
さすがデジタルネイティブ
Pythonistaはアプリも作れる
Pythonistaの使い方まとめ - みやびのどっとぴーわい
そのうちタッチ操作できるようにできたらいいね
21 May 2020 追記
この記事のコードを少し書き直した
問題を選ばせるところ
新しく記事を書いたのでリンクを貼る
mecobalamin.hatenablog.com
追記ここまで
30 November 2020 追記
書き直してみた
共通する変数があるときに同じモジュール内に記述する
class MathEquations: def __init__(self, a, b, c, d, equation_type): self.a = a self.b = b self.c = c self.d = d self.equation_type = equation_type def exam_equation(self): kotae = '' amari = '' shiki = '' if self.equation_type == '1': kotae = self.a + self.b shiki = r'$\displaystyle' + str(self.a) + " + " + str(self.b) + ' = $' kotae = r'$' + str(kotae) + '$' elif self.equation_type == '2': kotae = round(self.a * self.b, 1) shiki = r'$\displaystyle' + str(self.a) + '\\times' + str(self.b) + ' = $' kotae = r'$' + str(kotae) + '$' elif self.equation_type == '3': kotae = round(self.a // self.b, 1) amari = self.a % self.b shiki = r'$\displaystyle' + str(self.a) + '\\div' + str(self.b) + ' = $' kotae = r'$' + str(kotae) + '\\cdots' + str(amari) + '$' elif self.equation_type == '4': kotae = self.a + self.b shiki = r'$\displaystyle\frac{' + str(self.a) + '}{' + str(self.c) + '} + \\frac{' + str(self.b) + '}{' + str(self.c) + '} = $' kotae = r'$\displaystyle\frac{' + str(kotae) + '}{' + str(self.c) + '}$' return([shiki, kotae, self.d]) | class GenerateNumbers: def __init__(self, n, x, y, z): self.n = n self.x = x; self.y = y; self.z = z self.a = []; self.b = []; self.c = [] def generate_int(self): for i in range(self.n): self.a.append(random.randrange(10 ** (self.x - 1), 10 ** self.x)) self.b.append(random.randrange(10 ** (self.y - 1), 10 ** self.y)) self.c.append(random.randrange(2, 99)) return(self.a, self.b, self.c) def generate_decimal(self): for i in range(self.n): self.a.append(random.uniform(10 ** (self.x - 1), 10 ** self.x)) self.b.append(random.uniform(10 ** (self.y - 1), 10 ** self.y)) self.c.append(random.uniform(10 ** (self.z - 1), 10 ** self.z)) return(self.a, self.b, self.c)