/ 最近 .rdf 追記 設定 本棚

脳log[2011-02-09~]



2011年02月09日 (水) カレーライスのライスは右か左か。答えはでてるんだろうか。右利きだから左にご飯があると、1.スプーンをご飯に突き立てる。2.右側からカレーを巻き込みながらご飯のブロックをすくい上げる。という動作がスムーズに行えるな、なんて事を考えるんだけど、ぶっちゃけどっち向きでも食べられるし、量が減ってくるとお皿に熱を奪われたくなくて、縦向きに持って手前に寄せて食べてる。

最終更新: 2011-02-10T04:56+0900

[ProjectEuler] Q51, Q52, Q53, Q55

 Q51

ただただ、手と CPUを動かすだけで精一杯。(頭は役に立ってないよ)

primes = [2]
is_prime = lambda{|x|
	result = true
	primes.each{|prime|
		quo, rem = x.divmod(prime)
		if rem == 0
			result = false
			break
		end
		break if quo < prime
	}
	return result
}

# replace 2 digits or 3 digits. キ・メ・ウ・チ
def find_8_prime_family(a)
	return [] if a.size < 8
	a.map!{|x| x.to_s }
	h = Hash.new{|h,k| h[k] = [] }

	# 2 digits
	0.upto(a.first.size-3){|i|
		(i+1).upto(a.first.size-2){|j|
			h.clear
			a.each do |prime|
				if prime[i] == prime[j]
					h[prime[0...i]+prime[(i+1)...j]+prime[(j+1)...(prime.size)]].push prime
				end
			end
			h.each do |_,v|
				return v if v.size == 8
			end
		}
	}

	# 3 digits
	0.upto(a.first.size-4){|i|
		(i+1).upto(a.first.size-3){|j|
			(j+1).upto(a.first.size-2){|k|
				h.clear
				a.each do |prime|
					if prime[i] == prime[j] and prime[j] == prime[k]
						h[prime[0...i]+prime[(i+1)...j]+prime[(j+1)...k]+prime[(k+1)...(prime.size)]].push prime
					end
				end
				h.each do |_,v|
					return v if v.size == 8
				end
			}
		}
	}

	return []
end

x = 1
start = 0 # start of primes of a width.
loop {
	x += 2
	next unless is_prime.call x
	print "#{x}\r"
	if primes[start].to_s.length != x.to_s.length
		a = find_8_prime_family primes.last(primes.size-start)
		if ! a.empty?
			puts a.sort.join(" ")
			exit
		end
		start = primes.size
	end
	primes.push x
}

 Q52

桁数ごとに探索範囲を決めて、総当たり。

問題が xについても同じ数の組み合わせであることを求めてると思わなくてチェックしてないけど、結果的に xも 2x,3xなんかと同じ数字で構成されてた。

digits = 10
loop {
	digits *= 10
	(digits/2).upto((digits*10-1)/6){|x|
		print "#{x}\r"
		x2 = (x*2).to_s.split(//).sort
		if [3,4,5,6].all?{|n|
			x2 == (x*n).to_s.split(//).sort
		} then
			puts [1,2,3,4,5,6].map{|n| x*n }.join(" ")
			exit
		end
	}
}

 Q53

浮動小数点数なんてファジーなものを使っちゃったよ。Math.sqrtの使用をこれまで頑なに避けてたのも、結果が Floatになるからだったり。

count = 0
23.upto(100){|n|
	cmb = 1.0
	1.upto(n/2){|r|
		cmb /= r
		cmb *= (n-r+1)
		count += (n-r == r) ? 1 : 2 if 1_000_000 < cmb
	}
}
p count

 Q55

問題文が難しかった。3割ぐらいは推測。

あっけなく答えが出たので to_s.reverse.to_i みたいなのをなくすべく、Integer#reverse を自作してみたら、かえって遅くなったし。

class Integer
	# 負数については考えてない。
	def reverse
		x = 0
		this = self
		begin
			this, rem = this.divmod(10)
			x = 10*x + rem
		end while 0 < this
		x
	end
end

count = 0
10.upto(10_000-1){|x|
	is_lychrel = true
	50.times{
		x = x + x.reverse
		if x == x.reverse
			is_lychrel = false
			break
		end
	}
	count += 1 if is_lychrel
}
p count

2011年02月08日 (火)

最終更新: 2011-02-09T20:16+0900

[ProjectEuler] Q50

 Q50

  1. 100万未満の素数リストを作成。
  2. リストをコピーして作業領域とする。
  3. コピーしたリストの要素に、一つ右の位置の素数、二つ右の位置の素数、以下略を加えていき、都度、和が素数かどうか確かめる。

時間がかかるので逐一進捗を表示してる。この問題に魔法の一手なんてあるのかね。

primes = []
is_prime = lambda{|x|
	result = true
	primes.each{|prime|
		quotient, remainder = x.divmod(prime)
		if remainder == 0
			result = false
			break
		end
		break if quotient < prime
	}
	return result
}
2.upto(999_999){|x|
	primes.push x if is_prime.call x
}
puts "#{primes.size} primes under 1 million."

work = primes.dup
step = 0
primes_found = []
live_elements = work.size
while 0 < live_elements
	step += 1
	primes_found.clear
	live_elements = 0
	print "step #{step}\r"
	0.upto(work.size-1-step){|i|
		work[i] += primes[i+step]
		if work[i] < 1_000_000
			live_elements += 1
			primes_found.push work[i] if is_prime.call work[i]
		end
	}
	if primes_found.empty?
	elsif primes_found.size < 10
		puts "step #{step}: #{primes_found.join ' '}"
	else
		puts "step #{step}: #{primes_found.size} primes"
	end
end

魔法の一手はなくても……

  • 素数列の作成と和の評価を同時進行にできるかも。
  • 作業領域の範囲の狭め方が下手。
  • 奇数ステップ(偶数個の素数の和)は不要。
  • 100万に近い素数は不要。(それを一つ加えただけで 100万を超えるんでは項数を稼げない)
  • 項数の上限は求められる。

答えを出した後でググるのが楽しい。フォーラムは読んでないけど、多分これ以上ないっていうような答えが書いてありそうで、面白くなさそうな気がしてる。(理解できない数学的知識が使われてたら、print XXXXXXX(answer); って書かれてるのと変わらないから)


2011年02月07日 (月) 間違いさがし。『コールド メディシン A錠』の背表紙に「COLD MEDICINE CAPUSULE A」って書いてある。

最終更新: 2011-02-09T01:05+0900

[ProjectEuler] Q47, Q48, Q49

 Q47

昨日よりちょっとはマシになったかと。アホすぎた素数判定を、素因数の数を数える処理と一体化した。でも 10秒以上かかります。

primes = [2]
have4primefactors = []

num_of_factors = lambda{|x|
	prime_factors = 0
	primes.each{|prime|
		quotient, remainder = x.divmod(prime)
		if quotient < prime
			prime_factors += 1
			break
		end
		if remainder == 0
			prime_factors += 1
			break if 4 < prime_factors
			x /= prime while x % prime == 0
			break if x == 1
		end
	}
	return prime_factors
}

x = 2
loop {
	x += 1
	print "#{x}\r"
	case num_of_factors.call(x)
	when 1
		primes.push x
		have4primefactors.clear
	when 4
		have4primefactors.push x
		p have4primefactors.first if have4primefactors.length == 4
	else
		have4primefactors.clear
	end
}

 Q48

恥ずかしいほどまっすぐで乱暴なスクリプトだけど、コンソールの表示も待てないくらいノーウェイトで答えが出るんだから仕方がない。

p (1..1000).inject(0){|sum,x| sum + x**x }

 Q49

  1. 4桁の素数リストを作る
  2. リストから条件を満たす二つの素数を選ぶ
  3. 計算で求めた三番目の数(三つのうち一番大きい)が条件を満たすか調べる。

10秒くらいかかります。

primes = []

is_prime = lambda{|x|
	result = true
	primes.each{|prime|
		quotient, remainder = x.divmod(prime)
		if remainder == 0
			result = false
			break
		end
		break if quotient < prime
	}
	return result
}

2.upto(9999){|x|
	primes.push x if is_prime.call x
}

primes_4digit = primes.last(primes.length - primes.rindex{|x| x < 1000 } - 1)
0.upto(primes_4digit.size-1){|i|
	p = primes_4digit[i]
#	next if p == 1487
	(i+1).upto(primes_4digit.size-1){|j|
		q = primes_4digit[j]
		r = q + q - p
		next if p.to_s.split(//).sort != q.to_s.split(//).sort or
		        q.to_s.split(//).sort != r.to_s.split(//).sort
		k = nil
		(j+1).upto(primes_4digit.size-1){|_k|
			if r == primes_4digit[_k]
				k = _k
				break
			elsif r < primes_4digit[_k]
				break
			end
		}
		if k
			puts "#{p} #{q} #{r}"
#			exit
		end
	}
}

2011年02月06日 (日)

最終更新: 2011-02-07T05:28+0900

[ProjectEuler] Q46, Q47

 Q46

squares[]はソート済みなのに .include?()でそれを活かせないのが不満。

primes = [] # Omit 2. Even prime is not needed.
squares = [1]
def prime?(n)
	return false if 0 == n%2
	3.step(n/2, 2) {|x|
		return false if 0 == n%x
	}
	return true
end

x = 1
loop {
	x += 2
	squares.push((squares.size+1)**2) if squares.last < x
	if prime?(x)
		primes.push x
		next
	end
	print "#{x}\r"
	next if primes.any?{|prime| prime < x and squares.include?((x-prime)/2) }
	p x # answer
	break
}

 Q47

何の工夫もないのですんごく時間がかかる。

def prime_gt2?(n)
	return false if 0 == n%2
	x, upper_bound = 3, n/2
	while x <= upper_bound
		upper_bound, remainder = n.divmod(x)
		return false if 0 == remainder
		x += 1
	end
	return true
end

primes = [2]
have4primefactors = []
have4primefactor = lambda{|x|
	num_of_factors = 0
	primes.each{|prime|
		if x % prime == 0
			num_of_factors += 1
			break if 4 < num_of_factors
			x /= prime while x % prime == 0
		end
	}
	return num_of_factors == 4
}

x = 2
loop {
	x += 1
	print "#{x}\r"
	if prime_gt2? x
		primes.push x
		have4primefactors.clear
	elsif have4primefactor.call(x)
		have4primefactors.push x
		p have4primefactors.first if have4primefactors.length == 4
	else
		have4primefactors.clear
	end
}

2011年02月05日 (土)

最終更新: 2011-02-05T10:26+0900

[ProjectEuler] Q14, 『珠玉のプログラミング』, Collatz予想

ちょっと前の日記から……

Q14

この漸化式は『珠玉のプログラミング』で見た。どうして収束するのかわからなかった。

見たっていうのはコラム4の問題で。

4.6問題

5.入力xが正の整数であるとき、以下のループが終了することを示してください。

while x != 1 do
  if xが偶数なら
    x = x/2
  else
    x = 3*x+1

これがまんま「コラッツの問題 - Wikipedia)」と呼ばれる未解決の問題だということに、今日「d.y.d.」を読んでいて気がついた。本の巻末のヒントを読み直してみたらこんなことが書いてあるし。

もし、この問題が解けたら、近くの大学の数学科に急いで行って、博士号を申請しましょう。

ひどい(笑)。わからなくて当然だ。遅刻学生が黒板の問題を宿題だと思って解いて提出したら、それは未解決問題だったとかいうのは、お話の世界なんだから。


2011年02月03日 (木)

最終更新: 2011-02-05T05:33+0900

[ProjectEuler] Q45

 Q45

無駄にこったねえ。一瞬 JavaScriptで書こうとしたしたせいか、lambda多用。

generators = [
	lambda {
		n, tn = 1, 1
		lambda { n+=1; tn+=n; tn } # triangle numbers generator
	}.call,
	lambda {
		n, pn = 1, 1
		lambda { pn+=3*n+1; n+=1; pn } # pentagonal numbers generator
	}.call,
	lambda {
		n, hn = 1, 1
		lambda { hn+=4*n+1; n+=1; hn } # hexagonal numbers generator
	}.call
]
numbers = [1, 1, 1] # Ti, Pj, Hk
relations = "===" # Ti?Pj, Pj?Hk, Hk?Ti
actions = lambda {
	relation = lambda {|a,b|
		a==b ? '=' : a>b ? '>' : '<'
	}
	when_Nth_is_the_smallest = lambda {|i|
		lambda {
			numbers[i] = generators[i].call
			relations[i] = relation.call(numbers[i], numbers[(i+1)%numbers.size])
			j = (i-1) % relations.size
			relations[j] = relation.call(numbers[j], numbers[(j+1)%numbers.size])
			print "#{numbers[i]}\r"
		}
	}
	(0..2).map{|i| when_Nth_is_the_smallest.call(i) }
}.call
action_table = Hash.new {|h,rel|
	raise "missing action for '#{rel}'"
}
[
	["<<>", "<>>", "<=>", "=<>", "<>="], # when Ti is the smallest
	["><<", "><>", ">=<", "><="], # when Pj is the smallest (and Ti not)
	[">><", "<><", "=><"], # when Hk is the smallest (and the other not)
].each_with_index {|rels, i|
	rels.each {|rel| action_table[rel] = actions[i] }
}
action_table["==="] = lambda {
	puts numbers[0] # answer
	actions[0].call
}
loop {
	action_table[relations].call
}

相当な時間をかけて(求められていない)三番目の数字が出た。>57722156241751


六角数は三角数なので、三角数は無視できる。五角数と六角数を並べて比較していくだけ。

それがわからない。


チート

Hn = n(2n-1) = (2n-1)(2n)/2 = m(m+1)/2 = Tm (m = 2n-1)

nは自然数だから、mは正の奇数になる。Triangle Numbersの奇数番目が Hexagonal Numbers.(逆も真) 言われたらそうかもね。それぞれの数列を眺めてたら気付くかもね。(それが無理なのはわかってる)


2011年02月02日 (水)

最終更新: 2011-02-03T09:33+0900

[ProjectEuler] Q43, Q44

 Q43

愚直に。

divisors = [17, 13, 11, 7, 5, 3, 2, 1]
candidates = []
div = divisors.shift
div.step(999, div){|x|
	triplet = [x/100, x/10%10, x%10]
	candidates.push triplet if triplet.uniq!.nil?
}
until divisors.empty?
	div = divisors.shift
	candidates.size.times{
		candidate = candidates.shift
		(0..9).each{|d|
			if ! candidate.include?(d) && 0 == (100*d + 10*candidate[0] + candidate[1]) % div
				candidates.push [d] + candidate
			end
		}
	}
end
candidates.reject!{|c| c[0] == 0 }
p candidates.inject(0){|sum,c| sum + c.join("").to_i }

 Q44

最初に出てきた数字を書いたら通ったけど……。pentagonal numbersの名前の由来もわからんもんね。

_5 = [1] # [P1, P2,...]
_5_index = {1=>0} # 逆引き(Pn=>n-1)辞書
loop{
	i = _5.size
	_5.push(_5.last + 3*i + 1)
	_5_index[_5[i]] = i
	print "."
	(i-1).downto(0){|j|
		diff = _5[i] - _5[j]
		break if diff > _5[j]
		k = _5_index[diff]
		next unless k
		diff2 = _5[j] - _5[k]
		l = _5_index[diff2]
		next unless l
		puts
		puts  "D=#{_5[j]-_5[k]}"
		puts  "#{_5[j]-_5[k]} = P#{j+1}-P#{k+1}"
		puts  "#{_5[l]} = P#{l+1}"
		puts  "#{_5[j]+_5[k]} = P#{j+1}+P#{k+1}"
		print "#{_5[i]} = P#{i+1}"
		gets
	}
}

2011年02月01日 (火) 日本のメーカーさん。Webに取説PDFを置いてくれるのは便利(仕様表とならんで商品を知る一番有用な情報)だけど、商品のページからどうしてその商品の取説へ直接とべないのか。なにかの(笑)同意を取りつけて、その先は型番の羅列。知らねーよ。


2011年01月30日 (日) 前情報から戦闘はFF12に近いイメージでいたんですが、だいぶ違いました。 味方はオートで自分を操作ってところは同じだけど、ガードや緊急回避、物陰に隠れたりがあるからアクション性がかなり高め。かといってヒットアンドウェイしていればいいかというとそうでもなく、戦術をきちんと練っていないとすぐ死にますw」 FF12の戦闘は面白かった。でも、フィールド移動とシームレスにつながることや戦闘中に自由に移動できることに意味がなく、結局いつも通りのコマンドバトルなんだなあって気づいたときはがっかりだった。『ラストストーリー』は前評判通り面白そうだ。Wiiだけど。Wiiだけど。


2011年01月29日 (土)

最終更新: 2011-04-09T19:20+0900

[SakuraEditor] サクラエディタに複数行検索を導入する際に考慮する必要がある正規表現パターンへの細工。

今のサクラエディタはユーザーが入力したパターンに細工を施している。>「正規表現を使った検索・置換で、改行の意味を LFのみから CRも含むように。

サクラエディタでは改行をまたいだ検索ができないけど、将来できるようになると問題が生じる。(その根拠は20100709p01の実験による)

  • ^(改行文字の直後にマッチ)が CR直後(かつLF直前でないことが望ましい)にマッチしないことが露見する。
  • $(?<![\r\n])(?=\r|$) に置き換える現在の細工では、連続する改行と改行の間にマッチできない。

^(?:(?<=^|\n)(?=[\s\S])|(?<=\r)(?=[^\n])) に、$(?=\r\n?|(?<!\r)\n|(?<![\r\n])$) に置き換えるのでいいかなあ。用意した入力が期待した結果になるのは確認したけど、予期しない入力が予期しない結果になる可能性はやっぱりある。

 ^ や $ を、先読みや戻り読みを使ったパターンに置き換えることの副作用

戻り読みの中に ^ や $ を置けなくなる。複数行検索ができるようになったときには、戻り読みの中で行末を検知したくなることもあるかもしれないね。でも、できないね。


2011年01月28日 (金) Scala。Cの型はコンパイラに対するメモリの幅と解釈の指定。変数にひもつけられている。Rubyの型はメモリ上のデータにひもつけられている。変数には何もない。型付けされた変数が Rubyにあったら、定型のガード節をインタープリタに任せられるかもしれない。一部の実行時エラーがコンパイルエラーになる夢もみられるかもしれない。


2011年01月26日 (水) まどか☆マギカ。一人がパックンチョされたけどあまり効果的な死ではなかった。立場を異にする二人の先輩魔法少女がいる中、善人面して近づいてくる黄色(死んだ方)はうさんくさかった。対立する黒に対して、本当に悪い子なのかな、とピンク(主人公)が口にするように価値観が定まらない中で死なれても喪失感なんてない。むしろ死んだことで、本当に見た目通りに善人だったんだな、と確認したくらい。無駄な死だ。


2011年01月25日 (火)

最終更新: 2011-02-01T10:42+0900

[ProjectEuler] Q28, Q30, Q31, Q34, Q39, Q40, Q42, Q250

 Q28

sum = 1
1.upto((1001-1)/2){|d|
	sum += 2 * ( (2*d+1)**2 + (2*d+1)**2-3*2*d ) # (右上の数+右下の数)の倍で対角4数の和
}
p sum

 Q30

9の5乗が6万弱なので6桁までの探索で十分。

t = [0, 1, 2**5, 3**5, 4**5, 5**5, 6**5, 7**5, 8**5, 9**5]
sum = 0
10.upto(999999){|n|
	sum += n if n == [n, n/10, n/100, n/1000, n/10000, n/100000].inject(0){|a,x| a+t[x%10] }
}
p sum

 Q31

キレイに書けたんではないかと。

coins = [200, 100, 50, 20, 10, 5, 2] # ,1
remainder = [200]
coins.each{|coin|
	remainder.length.times{|n|
		remain = remainder[n]
		while coin <= remain
			remain -= coin
			remainder.push remain
		end
	}
}
p remainder.size

メモリも CPUも節約できる真にすばらしい回答はこちら >Dreamshire | Project Euler Problem 31 Solution

target = 200
coins = [1,2,5,10,20,50,100,200]
ways = [1]+[0]*target
coins.each{|coin|
	coin.upto(target){|i|
		ways[i] += ways[i-coin]
	}
}
p ways[target]

ways[]のインデックスが残金(200-i㌺)で、値が場合の数、なのかな?

有名な問題で、SICPやら何やらに載ってるらしい。2005年以来封印してきたコンクリートマテマティクスを繙くときが来たのかもしれない。<もったいぶってないで勉強しろ

 Q34

def factorial(n)
	r = 1; n.downto(2){|x| r *= x }; r
end
factorials = [1]
9.times{ factorials.push( factorials.last * factorials.length) }

# 9の階乗が36万ちょっとなので 7桁までで十分
sum = 0
10.upto(9999999){|n|
	x = n
	m = 0
	while 0 < x
		m += factorials[x%10]
		x /= 10
	end
	sum += n if n == m
}
p sum

 Q39

Q9の発展。

best_p = 0
solutions_for_p = 0
3.upto(1000){|p|
	solutions = 0
	1.upto(p/3){|a|
		aa = a*a
		p_a = p-a
		a.upto(p_a/2){|b|
			solutions += 1 if aa + b*b == (p_a-b)*(p_a-b)
		}
	}
	if solutions_for_p < solutions
		solutions_for_p = solutions
		best_p = p
	end
}
p best_p

 Q40

# 一桁 1-9 9個
# 二桁 10-99 90個
# 三桁 100-999 900個
answer = 1
a = [1, 10, 100, 1000, 10000, 100000, 1000000]
width, count = 1, 9
n, pos = 1, 1
loop{
	count.times{
		if a.first < pos + width
			answer *= n.to_s[a.first-pos,1].to_i
			a.shift
			if a.empty?
				p answer
				exit
			end
		end
		n += 1
		pos += width
	}
	width, count = width+1, count*10
}

 Q42

names = ["A","ABILITY","ABLE",...]
name_values = names.map{|name| (0...(name.length)).inject(0){|wv,i| wv + name[i] - ?A + 1 } }.sort
count = 0
n, tn = 1, 1
until name_values.empty?
	name_values.shift while ! name_values.empty? and name_values.first < tn
	while ! name_values.empty? and name_values.first == tn
		count += 1
		name_values.shift
	end
	n, tn = n+1, tn+n+1	
end
p count

 Q250

わかんね。1^1, 2^2から 250250^250250までを、250で割った余りで 250種類に分類するところまでやったけど、そこから組み合わせの数を妥当な時間で計算できる気がしない。1要素で 250の倍数になるもの、ならないもの、2要素で 250の倍数になるもの、ならないもの、……、249要素で 250の倍数になるもの、を考えていくのかと思ったけど、それらの要素が有限なために自由には組み合わせられない(不可能な組み合わせが生じる)、単純に掛け合わせて可能な場合の数を求められない、というところで行き詰まった。ならばと、Q31で参考にしたスクリプトを下敷きに 250で割った余りをインデックスに、場合の数を値にした配列を使おうかと思ったけど、残金をインデックスにした場合と違って余りは循環する、というあたりで処理が一直線に進まなくてギブアップ。

memo = [[0, 1]]*250 # [exp, mod]
memo2 = (0...250).map{|x| x**250 } # exp=250特化版
set = [0]*250
1.upto(250250).each{|i|
	basemod = i%250
	mod = (memo[basemod][1] * (i-memo[basemod][0] == 250 ? memo2[basemod] : basemod**(i-memo[basemod][0]))) % 250
	memo[basemod] = [i, mod]
	set[mod] += 1
}
p set