超ひさしぶりに頭を使うことにしよう。
結構ポピュラーな数字パズルを解く。
SEND
+MORE
-------------
MONEY
を考える。言語はなんでも解けると思うけど今はpythonで
最初は総当たりのもっとも原始的なループでの方法を考える。
変数 S,E,N,D,M,O,R,E,Yをすべて0−9のループで回す。
できたのがこれ
#SEND+MORE=MONEYを総当たりで解く
for s in range(10):
for e in range(10):
for n in range(10):
for d in range(10):
for m in range(10):
for o in range(10):
for r in range(10):
for e in range(10):
for m in range(10):
for y in range(10):
if (s*1000+e*100*n*10+d)+(m*1000+o*100+r*10+e)==m*10000+o*1000+n*100+e*10+y:
if s>0 and m > 0:
print(s*1000+e*100*n*10+d,m*1000+o*100+r*10+e,m*10000+o*1000+n*100+e*10+y)
なんだかすごいことになっている。ちょっとこれはないわ。プロンプト帰ってこないし・・
あ、eとmがダブってループしてました、酷い。
そもそもいくら総当たりとはいえrangeですべて回すのは頭悪すぎ
14行めのif s>0 and m>0: はこれが無いと平気で 3009,301,3310とか出力してきちゃうので各変数文字の重複を禁止するのと4桁なり5桁の数値の頭が0じゃない判断くらいはしろよと・・
で、ほんのちょっとだけ数学的に考えると同桁の数値を足して繰り上がるのは1しかないのでm=1は確定だし下からの繰り上がりを考慮してもm(=1)と足して繰り上がることができるsは8か9になる。この辺りの縛りと重複を避けるようにして先程のプログラムに手を入れると
#SEND+MORE=MONEYを総当たりで解く
#各変数は重複せずm=1,sは8 or 9で考えると
m=1
for s in [8,9]:
kouho = list(range(10))
kouho.remove(m)
kouho.remove(s)
for e in kouho:
kouho.remove(e)
for n in kouho:
kouho.remove(n)
for d in kouho:
kouho.remove(d)
for o in kouho:
kouho.remove(o)
for r in kouho:
kouho.remove(r)
for e in kouho:
kouho.remove(e)
for y in kouho:
if (s*1000+e*100*n*10+d)+(m*1000+o*100+r*10+e)==m*10000+o*1000+n*100+e*10+y:
print(s*1000+e*100*n*10+d,m*1000+o*100+r*10+e,m*10000+o*1000+n*100+e*10+y)
となる。だけど上の方法ではうまくループが回らない。
(ああ、ここでもeを重ねてループしてるわ、リハビリ必要)
e以下のremoveを止めると・・・・あー分からない もう少し頭を冷やして考えよう
そもそもいろいろ忘れていてコードの効率が悪い。
重複のチェックにsetを使うことまでは頭が回るけどkosuu= set()
kosuu.add(m)みたいに8個の変数でやる。これは素人以下。頭を冷やそう。
#SEND+MORE=MONEYを総当たりで解く
#各変数は重複せずm=1,sは8 or 9で考えると
m=1
for s in range(8,10):
for e in range(10):
for n in range(10):
for d in range(10):
for o in range(10):
for r in range(10):
for y in range(10):
if len(set([m,s,e,n,d,o,r,y]))==8:
send=s*1000+e*100+n*10+d
more=m*1000+o*100+r*10+e
money=m*10000+o*1000+n*100+e*10+y
if send+more==money:
print(send,more,money)
結局上のリストのようになりました。なんだかシンプル。まだまだpythonの基本がわかってない。
単に途中までパズルをときかかったのでもう少し進めると
m=1、s=8 or 9より判った分の文字と数値を入れ替えて s=8と仮にすると
8END
+1ORE
-------------
1ONEY となる。桁上りするのでE+0>10なのだが千の桁が桁上りすると0がゼロになるがそれだとE+O>10が満たせないのでS=9が確定、同時に0はゼロ これをはめ込むと
9END
+10RE
-------------
10NEY である。さらにこれでN=E+1なのでE+1+R(+1)=10+Eでカッコのの桁からの繰り上がりの有無を考えると、必要となるので(9が使われているので)R=8となる。見難いけど
9E(E+1)D
+108E
10(E+1)EY 2・3桁目は桁上りだけなのでD+E=10+YでDとEは(7,6)(7,5)のいずれかの組合せとなる(6,5)では和の1桁目が1となり既に使用済み。E=7とするとN=8となり不可
E=6なら
967D
+1086
1076Y となり繰り上がれるDは5のみだがY=1になるので不可 よってE=5
956D
+1085
1065Y で繰り上がれるDは7でYは2となる。
ちなみにパズルの答えは正しく
Send = 9567
More = 1085
Money = 10652
一応記述したプログラムも同じ解を表示しているので今日は良しとする。