Problem 99 - 指数的爆発
うほ。簡単。と思って取り組んでみたら罠が・・・。
指数の形で表される2つの数, 例えば 2^11 と 3^7, の大小を調べることは難しくはない. 電卓を使えば, 2^11 = 2048 < 3^7 = 2187 であることが確かめられる.
しかし, 632382^518061 > 519432^525806 を確認することは非常に難しい (両者ともに300万桁以上になる).
各行に1組が書かれている1000個の組を含んだ22Kのテキストファイル base_exp.txt から, 最大の数が書かれている行の番号を求めよ.
注: ファイル中の最初の二行は上の例である.
Schemeはこういうの得意だろうと思ってやってみたら・・・。
(define (problem99 data) (letrec ((iter (lambda (n max-n max-value lis) (if (null? lis) max-n (let ((e (expt (caar lis) (cadar lis)))) (if (> e max-value) (iter (+ n 1) n e (cdr lis)) (iter (+ n 1) max-n max-value (cdr lis)))))))) (iter 1 0 0 data))) (problem99 *data99*) ; 終わらず
最初の数行こなすのに何分かかかる。30分くらい回してみたけどムリだった。
むぅSchemeパワーを発揮してもムリだとわかったので、対数パワーを借りる。
公式はコレだ。
log a^b = b log a
指数的爆発には対数で挑め!!
(define (problem99 data) (letrec ((iter (lambda (n max-n max-value lis) (if (null? lis) max-n (let ((e (* (cadar lis) (log (caar lis) )))) (if (> e max-value) (iter (+ n 1) n e (cdr lis)) (iter (+ n 1) max-n max-value (cdr lis)))))))) (iter 1 0 0 data))) (problem99 *data99*) ; 709
すぐ終わりました。ハイ。
参考
- 基礎からよくわかる基礎解析
- 1989年発行。高校の先輩から貰った参考書を今でも使ってます。
先輩ありがとう!!