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

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

あなたとお子様は日本の宝です。
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桁の計算式をつくるように指定した上で自動生成する**プログラムを作成します。
**繰り上がりや繰り下がりも指定**できるようにしてしまいます。

最終的なコードは[以下の記事](URL "https://qiita.com/miyama_daily/items/d93f7bef1c19a75ccab8
")で！！

https://qiita.com/miyama_daily/items/d93f7bef1c19a75ccab8



**この記事は問題作成のパートです。**


# 足し算

入力として
N, M, kがありますが、
**N・・・int 桁数
M・・・int 桁数
k・・・boolean 繰り上がりありかどうか**
です。

```py: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 繰り下がりありかどうか**

```py: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}}

```

# 掛け算
これは簡単ですね

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

約数を列挙するのは[この記事](URL "https://qiita.com/LorseKudos/items/9eb560494862c8b4eb56")を参考にしました。

https://qiita.com/LorseKudos/items/9eb560494862c8b4eb56


```py: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}}


```



# これらの関数を使って、、、
[下記の記事](URL "https://qiita.com/miyama_daily/items/d93f7bef1c19a75ccab8
")でTkinterとreportlabを使用して実際にプリントできるようにします！！！

https://qiita.com/miyama_daily/items/d93f7bef1c19a75ccab8