乙Py先生のプログラミング教室
初学者のためのプログラミング学習サイト

算数

はいどうも今晩は
乙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の部分を変えてもらえば
いろんな数字の答えを求めることができます。

是非ご活用ください。


それでは









はいどーもー
乙pyです。

暇なので受験シーズンだし
有名中学の算数の問題をプログラムで解けないかと
思ったりしたわけですね。

インターネットの
Googleで調べたんですが
そこで問題が難しそうな学校を見つけてしまったんですね。

皆さん

難しい中学校って知ってます?

自分は近所の中学校に行ったので
知らないんですけど
問題を解いてみたんですねー

というものの第八弾です。


動画解説はこちら



始めの問題
有名中学の入試問題.014


これも一瞬で解けます。
for i in range(1,20):
    st = '2' + '0'*i +'7'
    if int(st)%27==0 and int(st)%81!=0:
        print(st)
        break
先頭が2で末尾が7、間が0という
条件を充しつつ
27で割り切れて、81で割り切れないというものが
1つでも見つかった時点で
プログラムは終了です。

条件の書き方もそこまで難しくはないと思います。


次の問題は
有名中学の入試問題.013

まずは図を把握しろという
難問でした。

図のルールがわかれば
プログラムに落とし込むのは容易です。

要は日本語の問題ですね。
きちんと仕様を理解するというのが
問題のポイント(笑)です。

1のコードは
num = [1,2,3,4,5,6,7,8,9,10,11,12]
q1 = []
for i in range(1,6):
    q1 = num
    num = [num[0],num[6],num[1],num[7],num[2],num[8],num[3],num[9],num[4],num[10],num[5],num[11]]
print(q1)

1回目は入れ替えが起きないので
入れ替えが始まるのは2回目からですね

その分を考慮する必要があります。

一旦数字の並びは
リストに格納し、その並びを求めることとしました。

2のコードは
num  = [1,2,3,4,5,6,7,8,9,10,11,12]
num1 = [1,2,3,4,5,6,7,8,9,10,11,12]
q2 = 1
for i in range(1,13):
    q2 +=1
    print(i,num)
    num = [num[0],num[6],num[1],num[7],num[2],num[8],num[3],num[9],num[4],num[10],num[5],num[11]]
    if num == num1:
        print(q2)
        break

元の数値の並びを置いておき
入れ替えをするものと並びを比較してあげるだけの
シンプルなコードです。

12個しか数字がないので
元と同じになるのに
12回以上は入れ替えが起きないだろうと
試行回数は減らしています。

3のコードは
num = [1,2,3,4,5,6,7,8,9,10,11,12]

for i in range(2006-1):
    num = [num[0],num[6],num[1],num[7],num[2],num[8],num[3],num[9],num[4],num[10],num[5],num[11]]
print(num)

単にその回数実行してあげるだけ
ただし、その回数には注意が必要ですね。


図で考えると
すごく難しそう

でもプログラムはシンプル

そんな問題でした。

この問題の図を作るのに
一番時間が掛かるという・・・・

解くのは一瞬

はいどーもー
乙pyです。

暇なので受験シーズンだし
有名中学の算数の問題をプログラムで解けないかと
思ったりしたわけですね。

インターネットの
Googleで調べたんですが
そこで問題が難しそうな学校を見つけてしまったんですね。

皆さん

難しい中学校って知ってます?

自分は近所の中学校に行ったので
知らないんですけど
問題を解いてみたんですねー

というものの第七弾です。


動画解説はこちら



まず始めの問題は

有名中学の入試問題.004

整数を文字にして連結していき
そこに出てくる1の個数を数えればいいだけの
シンプルな問題です。

コードは

ans1=''
for i in range(1,101):
    ans1+=str(i)
print(len(ans1))
ans2=''
for i in range(1,1001):
    ans2+=str(i)
print(len(ans2))
print(ans2.count('1'))

100回だろうと、1000回だろうと
コードの量はほとんど変わりません。

次の問題


有名中学の入試問題.003

細胞B,T

それぞれ1秒毎に
BはBとT
TはBとB

個数としてはどちらも
2倍に増えていますねーー

ということは
8秒後には2 ** 8
倍になっていそうですね

あとはその配分がどうなっているかということ

動画では初めはB
その後BとTの時で処理を分けて増やし
最後にどうなったのかを出力するようにしました。

sells = ['b']
for i in range(8):
    tmp = []
    for sell in sells:
        if sell =='b':
            tmp+=['b','t']
        else:
            tmp+=['b','b']
    sells=tmp

print(sells.count('b'))
print(sells.count('t'))

当初の目論見通り
BとTで足すと256個でしたね。

TとTで

TT兄弟

なんちゃって


はいどーもー
乙pyです。

暇なので受験シーズンだし
有名中学の算数の問題をプログラムで解けないかと
思ったりしたわけですね。

インターネットの
Googleで調べたんですが
そこで問題が難しそうな学校を見つけてしまったんですね。

皆さん

難しい中学校って知ってます?

自分は近所の中学校に行ったので
知らないんですけど
問題を解いてみたんですねー

というものの第六弾です。


動画解説はこちら



始めの問題
有名中学の入試問題.018


はい
非常に簡単な問題です。

1,2,3同時に答えを導くことができます。

コードは

ans1,ans2,ans3 = [],[],[]
for i in range(100,1000):
    if i%3==0 and i%111!=0:
        ans1.append(i)
    if i%2==0 or i%11==0:
        ans2.append(i)
    if (i%2==0 or i%11==0) and (i%3==0 and i%111!=0):
        ans3.append(i)
3桁の整数の分だけforループで1つ1つ調べて行くだけですね。
割り切れる と 割り切れない
の複合条件になるところがポイントでしょうか?

条件の優先順位のつけ方と and  or などの使い方が
問題を解くキーになりそうですね。


次の問題
有名中学の入試問題.016

この問題は2段構えとしました。

まずは
A,B,Cの仕事量がどのくらいになるのかというのを
計算しておかないと

ABCを1台づつ使った際の仕事量が計算できないです

from  itertools  import product

for a,b,c in product(range(1,10),range(1,10),range(1,10)):
    if (a+b)*35 == (a+b*3)*20 and (a+b)*35 == (a*2+c*5)*14:
        print(a,b,c)
        break

これでABCの仕事量が計算できました。
A:5
B:3
C:2

あとは元々
AとBで35日かかった仕事なので
ABCでX日掛かるかを求めれば良いだけですね。

a,b,c = 5,3,2
for x in range(35):
    if (a+b+c)*x == (a+b) *35:
        print(x)
        break

さすがに簡単すぎて
皆さん飽きてきましたよね?

プログラミング向きの
歯ごたえのある問題があると
いいですねーーー

まだまだ続きます


はいどーもー
乙pyです。

暇なので受験シーズンだし
有名中学の算数の問題をプログラムで解けないかと
思ったりしたわけですね。

インターネットの
Googleで調べたんですが
そこで問題が難しそうな学校を見つけてしまったんですね。

皆さん

難しい中学校って知ってます?

自分は近所の中学校に行ったので
知らないんですけど
問題を解いてみたんですねー

というものの第五弾です。


動画解説はこちら




始めの問題
有名中学の入試問題.020

まずは
小手調的な問題

N回何かする的なものは
プログラムは大得意な領域

ABCDEFGHを
EAFBGCHDするということは

整数を文字に直して
インデックスで操作できます。

あとはそれを100回繰り返してやるだけです。

こんな感じのコードにしました。
a = '12345678'
answer = ''
for i in range(100):
    a = a[4]+a[0]+a[5]+a[1]+a[6]+a[2]+a[7]+a[3]
    answer = a
print(answer)

インデックスと順番は1つズレるので
そこだけ注意ですね


次の問題

有名中学の入試問題.019


さて
これは
組み合わせの問題になりますね。

1,5,10,50円を複数枚
組み合わせて50円にする場合

1円は必ず5枚1セットになるので
for文ではカウンターを5ずつ上げることにしました。

答えは
50円になる組み合わせと
100円になる組み合わせのふた通りを変数に用意する。

こんな感じのコードを書きました。
ans50  = []
ans100 = []
for i1 in range(0,101,5):
    for i5 in range(0,21):
        for i10 in range(0,11):
            for i50 in range(0,3):
                if (i1+i5*5+i10*10+i50*50)==50:
                    ans50.append((i1,i5,i10,i50))
                if (i1+i5*5+i10*10+i50*50)==100:
                    ans100.append((i1,i5,i10,i50))            
4重ループは
少し汚いですね・・・・

itertoolsのProduct
なんかを使うとすっきり書けます。
from  itertools import product

ans50,ans100  = [],[]
for i1 , i5 , i10 , i50 in product(range(0,101,5),range(0,21),range(0,11),range(0,3)):
    if (i1+i5*5+i10*10+i50*50)==50:
        ans50.append((i1,i5,i10,i50))
    if (i1+i5*5+i10*10+i50*50)==100:
        ans100.append((i1,i5,i10,i50))  
print(len(ans50))
print(len(ans100)) 

どちらで書いても
実行される結果は一緒になります。

ネストされる階層が深すぎると
見づらくなるので
まとめてしまうのもアリです。

今回はここまで
ではまた。



このページのトップヘ