Project Eulerを再開してみる
大学学部一年のころだったかな。友達と二人でProject Eulerというサイトでよく遊んでいた。これは計算機科学的な問題が大量に掲載されているサイトで、登録すれば自分が解いた問題を集計してくれたり他の人の回答を眺めたりできる。
ずいぶんとアクセスしていなかったのだけど、最近になってふと思い出した。どうせ暇なので昔は解けなかった問題を潰していこうと思って一日に数問ずつ回答していってる。
普通に解くと何百時間も掛ってしまう問題を数秒で解くための工夫が必要になる問題が多いので結構歯ごたえがある。
とってもきれいに解けたり、
text.map! do |r|
roman = r
roman.gsub!('IV', 'IIII')
roman.gsub!('IX', 'VIIII')
roman.gsub!('XL', 'XXXX')
roman.gsub!('XC', 'LXXXX')
roman.gsub!('CD', 'CCCC')
roman.gsub!('CM', 'DCCCC')
(roman.count('I') +
roman.count('V') * 5 +
roman.count('X') * 10 +
roman.count('L') * 50 +
roman.count('C') * 100 +
roman.count('D') * 500 +
roman.count('M') * 1000)
end
text.map! do |n|
t = sprintf("%04d", n).chars.map(&:to_i)
roman = "#{'M' * t[0]}"
case t[1]
when 4 then roman += "CD"
when 9 then roman += "CM"
else roman += "#{'D' if t[1] >= 5}#{'C' * (t[1]%5)}"
end
case (n%100).div(10)
when 4 then roman += "XL"
when 9 then roman += "XC"
else roman += "#{'L' if t[2] >= 5}#{'C' * (t[2]%5)}"
end
case t[3]
when 4 then roman += "IV"
when 9 then roman += "IX"
else roman += "#{'V' if t[3] >= 5}#{'I' * (t[3]%5)}"
end
end
新しい知識を得たり(トポロジカルソートなんて初めて使った)
require 'tsort'
class Hash
include TSort
alias tsort_each_node each_key
def tsort_each_child(node, &block)
fetch(node).each(&block)
end
end
hash = Hash.new
log = File.read('keylog.txt').split.map{|k| k.split(//).map(&:to_i)}
log.each do |l|
hash[l[0]] = [] unless hash[l[0]]
hash[l[0]] << l[1] unless hash[l[0]].include?(l[1])
hash[l[1]] = [] unless hash[l[1]]
hash[l[1]] << l[2] unless hash[l[1]].include?(l[2])
end
hash[0] = []
puts hash.tsort.reverse.join
するのは楽しい。でも数学的に美しい解き方が見つからなくて、無理矢理に近い形で解いたとしてももちろんクリアにはなるけどイマイチ腑に落ちない。
プログラミングの腕ってプログラムしていないとどんどん落ちていくものだと実感する。もうC言語でプログラミングなんてネットで検索しながらじゃないと厳しいだろうなぁ(笑)