計算ドリル python(機能拡張)

今回は前回書いた「[計算ドリル python](https://qiita.com/banana19980702/items/d8ff4c1aaf5cbe8afc2a)」の機能を拡張していきます。付け加える機能は以下の通りです。　
#拡張機能
・問題番号の追加
・問題数を100問に増加
***
まずは問題番号の追加をしてきます。ここでコードが煩雑になるので関数という形で問題と答えを出力する処理をまとめていきます。コードは以下の通りです。

##問題番号追加コード

```python:問題の出力関数
def question_out_txt(): #問題を出力する関数
    for cnt in range(10):
        num1 = random.randint(1,9)
        num2 = random.randint(1,9)
        if (cnt + 1) / 10 < 1: #問題番号1桁の場合
            question = "(" + str(cnt + 1) + ")  " + \
                       str(num1) + " + " + \
                       str(num2) + " = "
        else :
            question = "(" + str(cnt + 1) + ") " + \
                       str(num1) + " + " + \
                       str(num2) + " = "
        answers.append(num1 + num2)
        f.write(question + "\n")
```       

```python:答えの出力関数
def answer_out_txt(): #答えを出力する関数
    f.write("\nA. ")
    for i,answer in enumerate(answers,1):
        out_ans = "(" + str(i) + ") "  + \
                  str(answer) + " "
        f.write(out_ans)
```
答えの出力関数ではインデックスを追加するために<b>enumerate関数</b>を使っています。この関数はイテラブルオブジェクトのインデックスを取得する関数です。スタートポイントを1にして、これで問題番号を設定しています。
##全体のコード

```python:計算ドリル
import random

answers = []

def question_out_txt(): #問題を出力する関数
    for cnt in range(10):
        num1 = random.randint(1,9)
        num2 = random.randint(1,9)
        if (cnt + 1) / 10 < 1:
            question = "(" + str(cnt + 1) + ")  " + \
                       str(num1) + " + " + \
                       str(num2) + " = "
        else :
            question = "(" + str(cnt + 1) + ") " + \
                       str(num1) + " + " + \
                       str(num2) + " = "
        answers.append(num1 + num2)
        f.write(question+"\n")

def answer_out_txt(): #答えを出力する関数
    f.write("\nA. ")
    for i,answer in enumerate(answers,1):
        out_ans = "(" + str(i) + ") "  + \
                  str(answer) + " "
        f.write(out_ans)

with open("keisan.txt","w") as f:
    question_out_txt()
    answer_out_txt()
```
```pyton:出力結果
(1)  7 + 1 = 
(2)  8 + 8 = 
(3)  5 + 2 = 
(4)  9 + 7 = 
(5)  5 + 9 = 
(6)  1 + 6 = 
(7)  4 + 5 = 
(8)  6 + 2 = 
(9)  5 + 3 = 
(10) 2 + 7 = 

A. (1) 8 (2) 16 (3) 7 (4) 16 (5) 14 (6) 7 (7) 9 (8) 8 (9) 8 (10) 9 
```

##問題数100問に増加
次に問題数を増やしていきます。形式としては5×20の形式で行うのですが、インデントも綺麗に揃えたいので半角スペースを使ってインデントを揃えていきます。コードは以下の通りです。

#問題数増加コード

```python:問題出力
def question_out_txt(): #問題を出力する関数
    for cnt in range(100):
        num1 = random.randint(1,9)
        num2 = random.randint(1,9)
        if (cnt + 1) / 10 < 1: #1桁の場合
            question = "(" + str(cnt + 1) + ")  " + \
                       str(num1) + " + " + \
                       str(num2) + " = "
        else :
            question = "(" + str(cnt + 1) + ") " + \
                       str(num1) + " + " + \
                       str(num2) + " = "
        answers.append(num1 + num2)
        if (cnt + 1) % 5 == 0:
            f.write(question + "\n")
        else:
            f.write(question + " ")
```
ここでは問題番号が一桁か二桁かでインデントがずれるので条件分岐で半角スペースの個数を指定して、インデントを揃えています。問題を出力する際に5の倍数のところで問題を改行しています。

```python:答え出力
def answer_out_txt(): #答えを出力する関数
    f.write("\nA.\n")
    for i,answer in enumerate(answers,1):
        if (i / 10 < 1) and (answer / 10 < 1): #番号1桁,答えが1桁
            out_ans = "(" + str(i) + ")  " + \
                      str(answer) + "  "
        elif (i / 10 < 1) and (answer / 10 >= 1): #番号1桁,答えが2桁
            out_ans = "(" + str(i) + ")  " + \
                      str(answer) + " "
        elif (i / 10 >= 1) and (answer / 10 < 1): #番号2桁,答えが1桁
            out_ans = "(" + str(i) + ") " + \
                      str(answer) + "  "
        else:                                     #番号2桁,答えが2桁
            out_ans = "(" + str(i) + ") " + \
                      str(answer) + " "

        if i % 5 == 0: #5の倍数の問題番号ごとに改行
            f.write(out_ans + "\n")
        else:
            f.write(out_ans + " ")
```
肝心なのは答え出力の処理です。問題番号と答えのそれぞれの桁数は一桁だったり、二桁だったりするので<b>条件分岐は2^2で4通り</b>になります。ここでも問題番号が5の倍数ごとに改行しています。

##全体のコード

```python:計算ドリル
import random

answers = []

def question_out_txt(): #問題を出力する関数
    for cnt in range(100):
        num1 = random.randint(1,9)
        num2 = random.randint(1,9)
        if (cnt + 1) / 10 < 1: #2桁未満の場合
            question = "(" + str(cnt + 1) + ")  " + \
                       str(num1) + " + " + \
                       str(num2) + " = "
        else :
            question = "(" + str(cnt + 1) + ") " + \
                       str(num1) + " + " + \
                       str(num2) + " = "
        answers.append(num1 + num2)
        if (cnt + 1) % 5 == 0:
            f.write(question + "\n")
        else:
            f.write(question + " ")

def answer_out_txt(): #答えを出力する関数
    f.write("\nA.\n")
    for i,answer in enumerate(answers,1):
        if (i / 10 < 1) and (answer / 10 < 1): #番号1桁,答えが1桁
            out_ans = "(" + str(i) + ")  " + \
                      str(answer) + "  "
        elif (i / 10 < 1) and (answer / 10 >= 1): #番号1桁,答えが2桁
            out_ans = "(" + str(i) + ")  " + \
                      str(answer) + " "
        elif (i / 10 >= 1) and (answer / 10 < 1): #番号2桁,答えが1桁
            out_ans = "(" + str(i) + ") " + \
                      str(answer) + "  "
        else:                                     #番号2桁,答えが2桁
            out_ans = "(" + str(i) + ") " + \
                      str(answer) + " "

        if i % 5 == 0: #5の倍数の問題番号ごとに改行
            f.write(out_ans + "\n")
        else:
            f.write(out_ans + " ")

with open("keisan.txt","w") as f: #テキストファイルをオープン
    question_out_txt()
    answer_out_txt()
```
```:出力結果
(1)  5 + 8 =  (2)  2 + 4 =  (3)  8 + 7 =  (4)  2 + 4 =  (5)  7 + 9 = 
(6)  8 + 8 =  (7)  8 + 5 =  (8)  7 + 8 =  (9)  2 + 1 =  (10) 3 + 1 = 
(11) 8 + 1 =  (12) 7 + 2 =  (13) 9 + 8 =  (14) 6 + 2 =  (15) 3 + 4 = 
(16) 9 + 9 =  (17) 5 + 7 =  (18) 7 + 5 =  (19) 4 + 9 =  (20) 4 + 8 = 
(21) 7 + 3 =  (22) 1 + 7 =  (23) 4 + 5 =  (24) 1 + 6 =  (25) 5 + 1 = 
(26) 4 + 7 =  (27) 9 + 4 =  (28) 8 + 4 =  (29) 5 + 4 =  (30) 3 + 5 = 
(31) 2 + 7 =  (32) 8 + 1 =  (33) 5 + 6 =  (34) 7 + 6 =  (35) 2 + 8 = 
(36) 9 + 9 =  (37) 5 + 3 =  (38) 6 + 1 =  (39) 3 + 1 =  (40) 3 + 2 = 
(41) 7 + 7 =  (42) 2 + 5 =  (43) 9 + 1 =  (44) 7 + 9 =  (45) 6 + 5 = 
(46) 5 + 8 =  (47) 8 + 4 =  (48) 2 + 2 =  (49) 3 + 2 =  (50) 3 + 9 = 
(51) 6 + 4 =  (52) 7 + 9 =  (53) 5 + 5 =  (54) 9 + 5 =  (55) 6 + 5 = 
(56) 9 + 6 =  (57) 2 + 2 =  (58) 1 + 7 =  (59) 9 + 7 =  (60) 5 + 5 = 
(61) 9 + 5 =  (62) 3 + 1 =  (63) 2 + 8 =  (64) 4 + 1 =  (65) 6 + 6 = 
(66) 6 + 6 =  (67) 4 + 6 =  (68) 8 + 8 =  (69) 7 + 1 =  (70) 2 + 8 = 
(71) 5 + 1 =  (72) 8 + 8 =  (73) 4 + 8 =  (74) 2 + 3 =  (75) 5 + 2 = 
(76) 8 + 7 =  (77) 6 + 8 =  (78) 7 + 6 =  (79) 2 + 1 =  (80) 4 + 9 = 
(81) 9 + 3 =  (82) 6 + 5 =  (83) 5 + 7 =  (84) 7 + 7 =  (85) 9 + 6 = 
(86) 9 + 9 =  (87) 8 + 6 =  (88) 2 + 4 =  (89) 7 + 6 =  (90) 9 + 6 = 
(91) 8 + 2 =  (92) 5 + 3 =  (93) 3 + 3 =  (94) 2 + 7 =  (95) 4 + 2 = 
(96) 3 + 6 =  (97) 6 + 6 =  (98) 8 + 8 =  (99) 1 + 9 =  (100) 8 + 1 = 

A.
(1)  13  (2)  6   (3)  15  (4)  6   (5)  16 
(6)  16  (7)  13  (8)  15  (9)  3   (10) 4  
(11) 9   (12) 9   (13) 17  (14) 8   (15) 7  
(16) 18  (17) 12  (18) 12  (19) 13  (20) 12 
(21) 10  (22) 8   (23) 9   (24) 7   (25) 6  
(26) 11  (27) 13  (28) 12  (29) 9   (30) 8  
(31) 9   (32) 9   (33) 11  (34) 13  (35) 10 
(36) 18  (37) 8   (38) 7   (39) 4   (40) 5  
(41) 14  (42) 7   (43) 10  (44) 16  (45) 11 
(46) 13  (47) 12  (48) 4   (49) 5   (50) 12 
(51) 10  (52) 16  (53) 10  (54) 14  (55) 11 
(56) 15  (57) 4   (58) 8   (59) 16  (60) 10 
(61) 14  (62) 4   (63) 10  (64) 5   (65) 12 
(66) 12  (67) 10  (68) 16  (69) 8   (70) 10 
(71) 6   (72) 16  (73) 12  (74) 5   (75) 7  
(76) 15  (77) 14  (78) 13  (79) 3   (80) 13 
(81) 12  (82) 11  (83) 12  (84) 14  (85) 15 
(86) 18  (87) 14  (88) 6   (89) 13  (90) 15 
(91) 10  (92) 8   (93) 6   (94) 9   (95) 6  
(96) 9   (97) 12  (98) 16  (99) 10  (100) 9  
```

#振り返り
長くなりましたが、今回は問題番号をつけたり問題数を増やしたりして機能を拡張していきました。インデントを揃えるのに条件分岐を考えるのに苦労しました。しかし、疑問点なのが問題数が<b>任意の数</b>になったときのインデントの処理はどうするのだということです。これから、もっと機能を拡張していきながらそれは解消していきたいと思っています。