/ 最近 .rdf 追記 編集 設定 本棚

脳log[20110308] Q62, Q63, Q64



2011年03月08日 (火) 本の虫: グラフィックカードのドライバーをアップデートしない低能達」 アップデートしないよ。ATI RADEON X1600 PROだもん。いまさら関連のある変更があるとも思えないし。って、調べてみたら一年前にリリースされた最新の(そしてたぶん最後の)バージョンがインストールされてた。カードを買い換えようにも最近の GPUはでかいしアイドル時の消費電力がたぶん今のカードの消費電力と同じくらいだと思うんだよね。無駄。

最終更新: 2011-03-12T03:46+0900

[ProjectEuler] Q62, Q63, Q64

 Q62

"exactly five" って書いてあるから、同じ数字の並べ替えで作れる立方数が 6以上あってもダメだと思うんだ。

memo = Hash.new{|h,k| h[k] = [] }
n = 0
k_length = 1
loop{
	n += 1
	cube = n*n*n
	k = cube.to_s.split(//).sort.join('')
	if k.length != k_length
		answer = memo.values.select{|cubes| cubes.size == 5 }
		if not answer.empty?
			answer.each{|cubes| p cubes }
			exit
		end
		memo.clear
		k_length = k.length
	end
	memo[k] << cube
}

 Q63

# (x-1)/x <= log10(n) < 1 (n = ?,?,...)
count = 0
x = 0
loop{
	x += 1
	boundary = (x-1.0)/x
	lower_bound = (1..9).to_a.reverse.find{|n| Math.log10(n) < boundary } || 0
	count += 9 - lower_bound
	break if lower_bound == 9
}
p count

またまたDreamshire | Project Euler Problem 63 Solution」の解答を検討してみたい。二重のループなんてない。logの計算だって 9回だけ。どういうことだ?

  1. 10の n乗は常に n+1桁になる。
  2. 9の n乗は 10の n乗より小さいため n+1桁には絶対に届かず、ある程度までは n桁を保つが、そのうち n-1桁に落ちる。
  3. 8の n乗は 9の n乗より早く n-1桁に落ちる。
  4. 以下 1の n乗まで。
  5. で、「ある程度」って具体的には?
  6. 10を約0.954乗すると 9になる。9は 10より 0.046(=1-0.954)程度小さい数だ。
  7. この 0.046がいくつ集まると 10一個分小さい(=桁が落ちる)ことになるだろう。21.7(=1÷0.046)だ。
  8. 9の場合、21乗までは n乗が n桁を保っているが 22乗は違う。

というストーリーをひねり出した。「9は 10より 0.046(=1-0.954)程度小さい数だ」ってくだりがいかにも苦しい。小数だからごまかしがきいてるけど、ぴったり 10一個分小さくなる場合は n桁、n-1桁、どっち? (たぶんまだ n桁だな。1^1がそう)

ともあれ、明かされてみればワンライナーの問題だったよ。

p (1..9).inject(0){|sum,n| sum + (1/(1-Math.log10(n))).floor }

常用対数を直接求めるメソッドが用意されてるあたりが Rubyだなとおもた。

 Q64

連分数っていうらしい。a_nの求め方、a += 1 while 0 <= r - (n - d*(a+1))**2 の条件部分が判然としない。スクリプト中のコメントにあるように、対象としてるルートの係数が必ず約分されて 1になることも理解できてない。

def next_frac(r, n, d) # (√r + n) / d = a + 1 / [(√r + n_) / d_]
	a = 0
	a += 1 while 0 <= r - (n - d*(a+1))**2
	d_ = (r - (n - d*a)**2) / d
	raise if (r - (n - d*a)**2) % d != 0 # why OK?
	n_ = -(n - d*a)
	return a, r, n_, d_
end

def period_of(r)
	rnd = [r, 0, 1]
	arr = []
	loop{
		a, *rnd = next_frac(*rnd)
		arr << rnd
		period = arr.size-1 - arr.index(rnd)
		return period if 0 != period
		return 0 if rnd[2] == 0 # √r is rational.
	}
end

count = 0
1.upto(10000){|n|
	count += 1 if period_of(n) % 2 == 1
}
p count

ところで、この問題を解くときに Math.sqrtを使うのってインチキくさくない?(だから使ってないんだけど)