日本語翻訳サイトは、プロジェクトオイラー日本語 でネット検索です。
問99「最大のべき乗」
指数の形で表される2つの数, 例えば 211 と 37, の大小を調べることは難しくはない. 電卓を使えば, 211 = 2048 < 37 = 2187 であることが確かめられる.
しかし, 632382518061 > 519432525806 を確認することは非常に難しい (両者ともに300万桁以上になる).
各行に1組が書かれている1000個の組を含んだ22Kのテキストファイル base_exp.txt から, 最大の数が書かれている行の番号を求めよ.
注: ファイル中の最初の二行は上の例である.
注意!!!
自力で解きたい人へ
以降の記述には解法に関するネタバレが含まれます。
私の回答例は以下の通りです。
# -*- coding:sjis -*- def f(sIn): import math pIn = open(sIn) c = 0 for i, r in enumerate(pIn.readlines()): a, b = r[:-1].split(",") v = int(b)*math.log10(int(a)) if c<v: c, line, rec, digit = v, i+1, r[:-1], int(v)+1 pIn.close() pIn = None return line, rec, digit sIn = os.path.join(os.path.dirname(__file__),"p099_base_exp.txt") line, rec, digit = f(sIn) print "line :", line print "rec :", rec print "digit:", digit
1.関数f(sIn)
・aのb乗をpとすると、
p = ab
両辺の10を底とする対数をとって、
log(p) = b x log(a)
なお、上記式の両辺の対数の底を10にすれば、
この両辺の値を切り捨て+1した値が桁数になります。
この式を実装して最大値を判定します。
・for i, r in enumerate(pIn.readlines()):
readline関数で1行ずつ読み込みます。
・a, b = r[:-1].split(",")
readline関数で末尾の改行コードは取り除かないので、末尾の1バイトを削除し、半角カンマで基数と指数に分けます。
・v = int(b)*math.log10(int(a))
vは、aのb乗の値の、10を底とする対数値です。
・if c<v: c, line, rec, digit = v, i+1, r[:-1], int(v)+1
対数値vの最大値をcにためます。
iは0から始まる行カウンタなので、行番号はi+1です。
readline関数で末尾の改行コードは取り除かないので、行内容recは末尾の1バイトを削除します。
digitは桁数です。
解答はこのすぐ下の行です。文字の色を白にしてます。選択状態にすると見えます。
line : 709
rec : 895447,504922
digit: 3005316
0 件のコメント:
コメントを投稿