「「1から9までの数字を一回ずつ使って2010にする」の検算」の検算
1+2-(3-4-5)*6*7*8-9
みなさん、あけましておめでとうございます。
特に新年のネタとかは用意していないので、マンションの門松の写真でお茶を濁そうと思います。
常山日記の 2010-01-05 [Python]巡回 05:13 で紹介されていた 「1から9までの数字を一回ずつ使って2010にする」の検算 - m_yamamo0417の日記 がちょっと気になったので調べてみました。
このページでなにをやっているかというと、1から9の数字を順番に使って 2010 という数字を作る式が大量に http://www.thesamet.com/2010.txt あります。 で、この式が正しいかどうかを python を使って検算しているんですが、検算の結果 645/925 しか答えが 2010 にならないとのことです。
で、パッと見「そんなに間違えてるのかな~」と思って気になりました。
例えば11行目にある数式の答えは0であると書いてあります。 で、ためしにこの数式をコピーして数式を処理できるツール(コマンドラウンちゃーの Launchy です)に渡してみると、 2010 と表示されました。
(1*2/3)*((4+5)*6*7*8-9):0
で、ためしに今度は python の対話モードでこの数式を指定するとこうなります。
>>> (1*2/3)*((4+5)*6*7*8-9) 0
やっぱり 0 になります。で、実は以下の数式がポイントでした。
>>> 2/3 0
python では整数同士の割り算の結果は整数を返すことになっているそうです。(普段あんまり気にしてなかった...) そのため、2/3 が 0.666666 ではなくて 0 になって全体の結果も 0 になると。 おそらく他の答えが合わないものも同じ理由なんじゃないかなーということで、検算のソースコードを修正してみると、全部 2010 になりました。
また、知らなかったんですが python 3 では int 同士の割り算は float を返すようになったそうです。へー。
参考: 言語としての一貫性を重視したPython 3の進化 - @IT
というわけで、コードを以下のように変更すると、全部 2010 になりました。 変更のポイントは、割り算が発生する場合は 1.0 をかけて float にする(手抜き)のと、答えの比較のときに round() を使って誤差をまるめるということです。
***************
*** 13,20 ****
total_count = 0
for matched in REGEX.findall(body):
cmd = matched
result = eval(cmd)
! if 2010 == result:
equal_count += 1
print cmd + ':' + str(result)
total_count += 1
--- 13,21 ----
total_count = 0
for matched in REGEX.findall(body):
cmd = matched
+ cmd = cmd.replace("/", "*1.0/")
result = eval(cmd)
! if 2010 == round(result):
equal_count += 1
print cmd + ':' + str(result)
total_count += 1
実行結果はこんな感じです。
((1+.2)*1.0/.3)*((.4-.5)*1.0/.6+7*8)*9:2010.0 ((1*1.0/.2)*3*1.0/.4)*(.5+6*(.7+8)+.9):2010.0 ((1*1.0/(.2+.3))*1.0/.4)*(5*(.6+78)+9):2010.0 ((1*1.0/.2)*1.0/.3)*((4+5)*(6-.7+8)+.9):2010.0 ((1*1.0/(.2-.3))*1.0/(.4-.5))*(6+7+8-.9):2010.0 eq/total 925/925
すっきり
しかし、この元データどうやって作ったんだろう。そっちが気になる。
- カテゴリ
-
python
-
- ¦
- 固定リンク
- ¦
- コメント (0)
- ¦
- トラックバック (0)
- トラックバック用URL:
- http://takanory.net/takalog/1192/tbping
鈴木たかのりです。とりあえず日記っぽく雑多なことを書き込んでいこうと思っています。
zope/plone関係の技術的な内容については