お子様がいるプログラマーのみなさん
あなたとお子様は日本の宝です。
Qiitaを徘徊している親御様はきっとお子様にいい教育を施したいと思っているに違いありません。(断定)
かく言う私も、こどもにはいい学校にいっていい職業に就いてほしいと思っています。
まあ正直に申し上げるとマジでいい職業に就いてほしいです。マジで。大切なことなので2回言いました。
私自身は運がいいことにそこそこいい学校に行けていい職業に就けたと思っているのですが、子どもにも同じようになってほしいと思い、幼少期に何をしていたのかを思い出してみたところ、、、、、
父親が無限に製造していた計算プリントをひたすら解いていて、3-4歳には割り算の筆算ができるようになっていました!!!
父親は偉大でしたです。
そんな父親のようになりたい、、、そんな私は、計算プリントを作ることを決意しました!
pythonで作る!excelやスプレッドシートではない理由
これは単純です。
自分、いまWindow userでexcelで作ってしまえばいいのですが、、、
Mac userになりたい!否、すでに数年後にDesktopのMacを買おうと決心しているのです。
Mac userになったら、NumbersやGoogle スプレッドシートしか使わなくなります。
なのでexcel VBAはボツ!
あれ、スプレッドシートでGASを用いて作ればいいのでは??
ああ、勘の良いガキは嫌いだよ。
好きな枚数のプリントを一気に自動生成したかったので、道筋が簡単に見えたpythonを選択しました。
GASでできるならGASでやりたいです。
できたら記事を作成したいです。
計算式を作ろう!
前提として、今回はTkinterを用いてN桁とM桁の計算式をつくるように指定した上で自動生成するプログラムを作成します。
繰り上がりや繰り下がりも指定できるようにしてしまいます。
最終的なコードは以下の記事で!!
この記事は問題作成のパートです。
足し算
入力として
N, M, kがありますが、
N・・・int 桁数
M・・・int 桁数
k・・・boolean 繰り上がりありかどうか
です。
import random
# 繰り上がり判定機
def k_up(N, M):
d_N = len(str(N))
d_M = len(str(M))
if d_N > d_M:
l = d_M
else:
l = d_N
for i in range(1, l+1):
if int(str(N)[-i]) + int(str(M)[-i]) >= 10:
return False
else:
continue
# 繰り上がりありならFalse、なしならTrueを返す
return True
def generate_temp_addition(N, M):
retern random.randint(10**(N-1), 10**(N)-1), random.randint(10**(M-1), 10**(M)-1)
def generate_addition(N, M, k):
# 繰り上がりなし
if k is False:
# Trueとなれば抜けられるようにする
while k is False:
n_N, n_M = generate_temp_addition(int(N), int(M))
k = k_up(n_N, n_M)
# 繰り上がりあり
else:
# Falseとなれば抜けられるようにする
while k is True:
n_N, n_M = generate_temp_addition(int(N), int(M))
k = k_up(n_N, n_M)
return {"N": n_N, "M": n_M, "ans": {"value": n_N+n_M}}
引き算
答えは正の値になるようにしています
N・・・int 桁数
M・・・int 桁数
k・・・boolean 繰り下がりありかどうか
import random
# 繰り下がり判定機
def k_down(N, M):
for i in range(1, len(str(M))+1):
if int(str(N)[-i]) < int(str(M)[-i]):
return False
else:
continue
def generate_temp_asubtraction(N, M):
retern random.randint(10**(N-1), 10**(N)-1), random.randint(10**(M-1), n_N)
def generate_subtraction(N, M, k):
# 繰り上がりなし
if k is False:
# Trueとなれば抜けられるようにする
while k is False:
n_N, n_M = generate_temp_subtraction(int(N), int(M))
k = k_down(n_N, n_M)
# 繰り下がりあり
else:
# Falseとなれば抜けられるようにする
while k is True:
n_N, n_M = generate_temp_subtraction(int(N), int(M))
k = k_down(n_N, n_M)
return {"N": n_N, "M": n_M, "ans": {"value": n_N-n_M}}
掛け算
これは簡単ですね
import random
def generate_multiplication(N, M):
n_N = random.randint(10**(N-1), 10**(N)-1)
n_M = random.randint(10**(M-1), 10**(M)-1)
return {"N": n_N, "M": n_M, "ans": {"value": n_N*n_M}}
割り算
N・・・int 桁数
M・・・int 桁数
s・・・boolean n÷nやn÷1を含むかどうか
a・・・boolean 余りありかどうか
割り算のみ割り切れる場合と余りを出す場合で答えの形式が違うのでretrunの形も少し違っています。
約数を列挙するのはこの記事を参考にしました。
import random
def make_divisors(n):
lower_divisors , upper_divisors = [], []
i = 1
while i*i <= n:
if n % i == 0:
lower_divisors.append(i)
if i != n // i:
upper_divisors.append(n//i)
i += 1
return lower_divisors + upper_divisors[::-1]
def generate_division(N, M, s, a):
if a is False:
p_divisors = []
while len(p_divisors) == 0:
n_N = random.randint(10**(N-1), 10**(N)-1)
divisors = make_divisors(n_N)
if s is False:
del divisors[0]
del divisors[-1]
p_divisors = [i for i in divisors if 10**(M-1) <= i <= 10**(M)-1]
n_M = random.choice(p_divisors)
else:
n_N = random.randint(10**(N-1), 10**(N)-1)
divisors = make_divisors(n_N)
if N == M:
n_M = random.randint(10**(M-1), n_N)
else:
n_M = random.randint(10**(M-1), 10**(M)-1)
while n_M in divisors:
if N == M:
n_M = random.randint(10**(M-1), n_N)
else:
n_M = random.randint(10**(M-1), 10**(M)-1)
return {"N": n_N, "M": n_M, "ans": {"value": int(n_N/n_M), "sho": n_N//n_M, "amari":n_N%n_M}}
これらの関数を使って、、、
下記の記事でTkinterとreportlabを使用して実際にプリントできるようにします!!!