はいどうも今晩は
乙pyです。

本日はまず
Youtube登録者数が
100人を突破いたしましたーーーーーーー

きゃー
うれスィー

こんな底辺YouTuberですが
登録者数1000人、1万人と目指して
今後とも頑張って行きたいと思います。

目標は
日本国民全員が
プログラミングできるようになること
プログラミングたーのしーって
思えるようになることを目指しておりますので
引き続き皆さま動画の方を
よろしくお願いいたします。

動画はこちら




今回は算数チャレンジです。
算数チャレンジとは?
140114nexus7_cm_pazzle


昔GoogleのCMでこんなのが有りましたね。
四つの数字を用いて
組み替えて10になるような計算方法を
考えましょうと言うもの。

1 1 5 8 
これに
+ー*/
で答えを10にしましょう。

・・・

実際これやってみると
意外と大変なものです。


これを自力で解くのは
結構頭を使うので
頭を使わないために
プログラムで解く方法を考えてみましょう(笑)。

まず考えるべきは
プログラムで使う部品です。

4つの数字
+-*/の記号

これだけだと
実は解けないんです。

計算では優先順位があるので
先に足すとかしたい場合は
カッコが必要になります。

このカッコ() を用いることができないと
算数の問題を解けません。

と言うことで
部品を揃えて行きましょう。

言語はPythonを用います。
Python言語では
分数の計算を行うことができる
Fractionと言うライブラリがあります。

これを用いると
通常は1/7など小数点になってしまい
計算が合わなくなってしまうのを
分数扱いできるので
正しく答えを求めることができます。

また、4つの数字は
色々組み替える必要があるので
この組み替えを行うために
itertoolsライブラリを用います。

まずはこの二つをインポートしておきます。
from fractions import Fraction
import itertools

次に
そう考えていくかと言うと
数式を作っていくことを考えます。

1+2+3+4

こんな感じで4つの数字と
記号を三つ組み合わせる式になるはずです。

加えてこれにカッコ()を付け足す形になるので
このかっこのパターンを含めた数式文字列の
パターンを用意してあげます。
pattern = [
    '%s%s%s%s%s%s%s',
    '(%s%s%s)%s%s%s%s',
    '(%s%s%s%s%s)%s%s',
    '%s%s(%s%s%s)%s%s',
    '%s%s(%s%s%s%s%s)',
    '%s%s%s%s(%s%s%s)',
    '(%s%s%s)%s(%s%s%s)'
]
このように
かっこのパターンを用意してあげます。

次に
数式をどう組み立てるかと言うと
このパターンの%sの部分に
数字と記号を当てはめて行きます。

for x, y, z in itertools.product('+-*/',repeat=3)


これで記号の全通りの組み合わせを作ることができます。
itertools.productはその文字数分だけ繰り返しが行われます。
repeat=3なので3文字分の記号の組み合わせを作成します。


QUESTION = '1158

for a, b, c, d in itertools.permutations(QUESTION,4)

文字の部分は
こんな感じになります。
permutationsで数字の順列を作成します。

この7つの文字を
先ほどのパターンに当てはめます。

f = p % (fa, x, fb, y, fc, z, fd)


これでfに数式が当てはまりました。
あとはこれを計算するのですが
この変数fの値は文字列なので
計算はできません。

Pythonでは
文字を数式として評価できる
eval()と言う関数があります。

これを用いると数式として計算ができるので
作成した文字を数式として扱って
計算した結果、10になったら
答えとして、結果を保存します。

結果はsetに格納して重複を排除しました。

プログラムを組み合わせると
こんな感じになります。

from fractions import Fraction
import itertools

pattren = [
'%s%s%s%s%s%s%s',
'(%s%s%s)%s%s%s%s',
'(%s%s%s%s%s)%s%s',
'%s%s(%s%s%s)%s%s',
'%s%s(%s%s%s%s%s)',
'%s%s%s%s(%s%s%s)',
'(%s%s%s)%s(%s%s%s)',
]
QUESTION = '1158'
result_set = set()
for x, y, z in itertools.product('+-*/',repeat=3):
    for a, b, c, d in itertools.permutations(QUESTION,4):
        fa, fb, fc, fd = ['Fraction(%s)' % n for n in [a, b, c, d]]
        for p in pattren:
            f = p % (fa, x, fb, y, fc, z, fd)
            try:
                result = eval(f)
            except ZeroDivisionError:
                continue
            if result == 10.0:
                result_set.add (p % (a, x, b, y, c, z, d))
for s in result_set:
    print(s)

この答えは
動画でご覧くださいませ。

さて
いかがでしょうか?

お子さんがいらっしゃる家庭であれば
宿題でこんな問題を
色々やらされことがあるかもしれませんが

このプログラムであれば
QUESTIONの部分を変えてもらえば
いろんな数字の答えを求めることができます。

是非ご活用ください。


それでは