1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

こどものために計算ドリルを作ってみたpython編 ①問題を作成する関数

Last updated at Posted at 2024-09-29

お子様がいるプログラマーのみなさん

あなたとお子様は日本の宝です。
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 繰り上がりありかどうか

です。

addition.py
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 繰り下がりありかどうか

subtraction.py
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}}

掛け算

これは簡単ですね

multiplication.py
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の形も少し違っています。

約数を列挙するのはこの記事を参考にしました。

division.py
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を使用して実際にプリントできるようにします!!!

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?