CodeIQで@Nabetani さんが出題されていた【100名限定】変進小数の足し算【手動採点】をRubyで解いてみました。
テストデータおよびソースコードのリビジョンはここからご確認できます。
解き方
小数の最下位から最上位に向かって1桁づつ順に足し算と繰り上げ処理をします。
足し算と繰り上げはNumeric#divmodを使えばシンプルに記述できると思います。
class Enumerator::Lazy
def filter_map
Lazy.new(self) do |yielder, *values|
result = yield *values
yielder << result if result
end
end
end
def add_var(v1, v2)
int1, fra1 = v1.split(?.)
int2, fra2 = v2.split(?.)
fra1, fra2 = [fra1, fra2].sort_by(&:size).map { |fra| fra.chars.map(&:to_i) }
fra3 = [*Array.new(fra1.size + 1, 0), *fra2[fra1.size..-1]]
fra1.size.downto(1) { |i| fra3[i-1], fra3[i] = (fra1[i-1] + fra2[i-1] + fra3[i]).divmod(11 - i) }
("%s.%s" % [int1.to_i + int2.to_i + fra3.shift, fra3.join]).to_r
end
def calc_formula formula
var = add_var(*formula.split(?+))
var.denominator == 1 ? var.numerator : var.to_f
end
def list_nonmatching_ids
File.foreach('data.txt').lazy.filter_map { |line|
id, formula, candidate = line.split("\t")
id unless candidate.to_r == calc_formula(formula)
}.force.join(?,)
end
puts ARGV[0] == "-d" ? list_nonmatching_ids : calc_formula(gets)