【Python】マッチ棒クイズ開発 Part3

こんにちは、にわこまです。

今回は、答えとなる正解の式から問題となる間違った式を生成する関数とその生成した間違った式が正しい式でないことを確認する関数を作成します。

 

誤字脱字や分からない点がございましたらご連絡お願いいたします!

メールまたはTwitterのDMまで!!

 

 

 

スポンサードサーチ


正解の式から間違った式を生成する関数の作成

Part2で作成したmakePlusFormula関数とmakeMinusFormula関数によって生成された式から間違った式を生成する関数を作成します。

間違った式とは「3 – 6 = 8」といったような式のことです。

 

今回のマッチ棒クイズ開発では、マッチ棒を1本しか動かさないということを前提にしています。そのため、間違った式とは以下の2つのどちらかの特徴を持ちます。

1. 数字または記号自身でマッチ棒を1本動かすと正しい式になる
2. 2つの数字または記号の内1つがマッチ棒を1本削除する、もう片方がマッチ棒を1本追加すると正しい式になる

 

例を以下に示します。上図は1の特徴を持ちます。「3」から「2」になるようにマッチ棒を移動させることで正しい式になります。下図は2の特徴を持ちます。「9」から「-」へマッチ棒を移動させると正しい式になります。

  

 

コードの提示

間違った式を生成する関数のソースコードを以下に示します。

def matchstickX(num, sticks):
    # 省略

def makePlusFormula():
    # 省略

def makeMinusFormula():
    # 省略

def makeQuestionFml(fml):
    qfml_list = []
    for i, num in enumerate(fml):
        transf_list = matchstickX(num, "plusminus")
        for transf in transf_list:
            new_fml = fml.copy()
            new_fml[i] = transf
            if(new_fml not in qfml_list):
                qfml_list.append(new_fml)
        transf_list_minus = matchstickX(num, "minus")
        for j, num2 in enumerate(fml):
            if(i == j):
                continue
            transf_list_plus = matchstickX(num2, "plus")
            for transf_plus in transf_list_plus:
                for transf_minus in transf_list_minus:
                    new_fml = fml.copy()
                    new_fml[i] = transf_minus
                    new_fml[j] = transf_plus
                    if(new_fml not in qfml_list):
                        qfml_list.append(new_fml)
    return qfml_list

if __name__ == '__main__':
    fml_list = ["8", "+", "0", "=", "8"]
    qfml_list = makeQuestionFml(fml_list)
    for qfml in qfml_list:
        print(qfml)

 

上記のコードは以下からダウンロードできます。

 

 

コードの解説

10行目から31行目の「makeQuestionFml関数」は、問題となる間違った式を生成する関数です。引数はリスト型の式(例:[“2”, “+”, “4”, “=”, “6”])です。

 

11行目の「qfml_list」は、リスト型にした間違った式を代入された変数です。最終的にこの変数を返却します。

 

12行目の「for文」は、引数の式の要素数だけ繰り返します。enumerate関数によって範囲を指定しているため、ループ変数はインデックス(i)と要素(num)になります。

  

13行目から18行目は、「数字または記号自身でマッチ棒を1本動かすと正しい式になる」という特徴を持った式を生成します。

 

13行目の「transf_list」は、matchstickX関数を使って要素(num)の1本移動(plusminus)させることによって変換できる数字または記号のリストを代入された変数です。

 

14行目の「for文」は、transf_listの要素数だけ繰り返します。ループ変数はtransfです。

 

15行目の「new_fml」は、引数のfmlをコピーしたリストが代入された変数です。fmlに対して操作を行ってしまうと、対象の式が分からなくなってしまうため、毎回コピーしています。

 

16行目は、numとtransfを入れ替えて間違った式を生成しています。

 

17行目の「if文」は、既にqfml_listに代入されていないか判定する条件文です。代入されていなければ18行目の処理を実行します。

 

18行目は、qfml_listに生成した間違った式を追加しています。

 

13行目から18行目の処理の流れを図として以下に示します。

 

 

19行目から30行目は、「 2つの数字または記号の内1つがマッチ棒を1本削除する、もう片方がマッチ棒を1本追加すると正しい式になる」といった特徴を持った式を生成します。

 

19行目の「transf_list_minus」は、matchstickX関数を使って要素(num)の1本削除(minus)させることによって変換できる数字または記号のリストを代入された変数です。

 

20行目の「for文」は、引数の式の要素数だけ繰り返します。enumerate関数によって範囲を指定しているため、ループ変数はインデックス(j)と要素(num2)になります。

 

21行目の「if文」は、インデックス(i)とインデックス(j)が同じ値であることを判別する条件式です。同じであれば22行目の「continue」を実行します。

インデックス(i)とインデックス(j)が同じであるということは、同じ数字または記号に対して1本削除と1本追加を行うということになります。これを避けるためにcontinueを実行します。

 

23行目の「transf_list_plus」は、matchstickX関数を使って要素(num2)の1本追加(plus)させることによって変換できる数字または記号のリストを代入された変数です。

 

24行目の「for文」は、transf_list_plusの要素数だけ繰り返します。ループ変数はtransf_plusです。

25行目の「for文」は、transf_list_minusの要素数だけ繰り返します。ループ変数はtransf_miunsです。

 

26行目の「new_fml」は、引数のfmlをコピーしたリストが代入された変数です。fmlに対して操作を行ってしまうと、対象の式が分からなくなってしまうため、毎回コピーしています。

 

27行目は、numとtransf_minusを入れ替えています。

同じく28行目は、num2とtransf_plusを入れ替えています。

 

29行目の「if文」は、既にqfml_listに代入されていないか判定する条件文です。代入されていなければ30行目の処理を実行します。

 

30行目は、qfml_listに生成した間違った式を追加しています。

 

19行目から30行目の処理の流れを図として以下に示します。

  

31行目の「return文」は、間違った式が代入されているqfml_listを返却しています。

  

 

動作確認

ードを保存したら、コマンドプロンプトを開きファイルを保存したフォルダまで移動します。移動したら、以下のコマンドを入力し実行します。

python matchstickquiz_QA.py

 

以下のように表示されれば動作確認完了です。

['0', '+', '8', '=', '8']
['6', '+', '8', '=', '8']
['9', '+', '8', '=', '8']
['8', '-', '8', '=', '8']
['8', '+', '6', '=', '8']
['8', '+', '9', '=', '8']
['8', '+', '8', '=', '0']
['8', '+', '8', '=', '6']
['8', '+', '8', '=', '9']

  

 

スポンサードサーチ


間違った式が正しい式でないことを確認する関数の作成

ここで作成する関数は先の関数によって生成された式が正しい式でないことを判別する関数です。

正しい式から間違った式を生成する際に、稀に正しい式から正しい式が生成されることがあります。それを回避するための関数です。例えば、「8 + 0 = 8」から「0 + 8 = 8」という式が生成されるということです。

 

 

コードの提示

正しい式でないことを判別する関数のソースコードを以下に示します。

def matchstickX(num, sticks):
    # 省略

def makePlusFormula():
    # 省略

def makeMinusFormula():
    # 省略

def checkFml(qfml):
    if(qfml[1] == "+" and int(qfml[0]) + int(qfml[2]) == int(qfml[4])):
        return True
    elif(qfml[1] == "-" and int(qfml[0]) - int(qfml[2]) == int(qfml[4])):
        return True
    return False

def makeQuestionFml(fml):
    qfml_list = []
    for i, num in enumerate(fml):
        transf_list = matchstickX(num, "plusminus")
        for transf in transf_list:
            new_fml = fml.copy()
            new_fml[i] = transf
            if(checkFml(new_fml)):
                continue
            if(new_fml not in qfml_list):
                qfml_list.append(new_fml)
        transf_list_minus = matchstickX(num, "minus")
        for j, num2 in enumerate(fml):
            if(i == j):
                continue
            transf_list_plus = matchstickX(num2, "plus")
            for transf_plus in transf_list_plus:
                for transf_minus in transf_list_minus:
                    new_fml = fml.copy()
                    new_fml[i] = transf_minus
                    new_fml[j] = transf_plus
                    if(checkFml(new_fml)):
                        continue
                    if(new_fml not in qfml_list):
                        qfml_list.append(new_fml)
    return qfml_list

if __name__ == '__main__':
    fml_list = ["8", "+", "0", "=", "8"]
    qfml_list = makeQuestionFml(fml_list)
    for qfml in qfml_list:
        print(qfml)

 

上記のコードは以下からダウンロードできます。

  

 

コードの解説

10行目から15行目の「checkFml関数」は、引数の式が正しい式かどうかを判別する関数です。引数はリスト型の式です。

 

11行目の「if文」は、足し算の式が正しい式であるかを判別する条件式です。正しい式である場合は、12行目で「True」を返します。

 

13行目の「if文」は、引き算の式が正しい式であるかを判別する条件式です。正しい式である場合は、14行目で「True」を返します。

 

15行目の「return文」は、「False」を返します。

 

makeQuestionFml関数のqfml_listに追加する前にcheckFml関数を実行しています。(ハイライト部分)

「True」が返されれば、continueを実行してqfml_listに追加させないようにしています。

 

 

動作確認

コードを保存したら、コマンドプロンプトを開きファイルを保存したフォルダまで移動します。移動したら、以下のコマンドを入力し実行します。

python matchstickquiz_QA.py

 

以下のように表示されれば動作確認完了です。

['6', '+', '8', '=', '8']
['9', '+', '8', '=', '8']
['8', '-', '8', '=', '8']
['8', '+', '6', '=', '8']
['8', '+', '9', '=', '8']
['8', '+', '8', '=', '0']
['8', '+', '8', '=', '6']
['8', '+', '8', '=', '9']

 

checkFml関数が含まれていないmakeQuestionFml関数の実行結果と比べて[‘0’, ‘+’, ‘8’, ‘=’, ‘8’]という式が無いことを確認してください。

 

 

スポンサードサーチ


まとめ

今回は、間違った式の生成とその生成された式の内正しい式を判別する関数を作成しました。

for文の中にfor文があり複雑ですが、1つひとつ手順を追っていくと理解出来ると思います。

それでも分からない場合はご連絡ください!

 

次回Part4では、実際に問題と答えを生成するためのmain関数を作成します。次回で問題と答えの生成は完成です。

 

 

 

最後までお読みいただきありがとうございます。


スポンサードサーチ