AOJ(問題集)11
AIZU ONLINE JUDGE: Programming Challenge
0100 Sale Result
問題が曖昧。同じ社員が二度出てくるかどうかはっきりしない。
Border = 1_000_000 until (n = $<.gets.to_i).zero? data = Hash.new(0) entry = [] n.times do e, p, q = $<.gets.split.map(&:to_i) data[e] += p * q entry << e if data[e] >= Border end puts entry.empty? ? "NA" : entry.uniq end
0101 Aizu PR
$<.gets.to_i.times do text = $<.gets.chomp result = "" po = 0 while result.size < text.size if text[po, 7] == "Hoshino" result += "Hoshina" po += 7 else result += text[po] po += 1 end end puts result end
0102 Matrix-like Computation
until (n = $<.gets.to_i).zero? table = n.times.map do l = $<.gets.split.map(&:to_i) l + [l.sum] end last = (n + 1).times.map do |i| n.times.map {|j| table[j][i]}.sum end puts (table + [last]).map {|l| l.map {|i| sprintf("%5d", i)}.join } end
簡単な問題でも [提出] のボタンを押すときはドキドキするな。
0103 Baseball Simulation
$<.gets.to_i.times do bases = [0, 0, 0] out_count = 0 points = 0 while out_count < 3 case $<.gets.chomp when "OUT" out_count += 1 puts points if out_count >= 3 when "HIT" bases << 1 points += bases.shift when "HOMERUN" points += bases.sum + 1 bases = [0, 0, 0] else raise "error" end end end
0104 Magical Tiles
ひさしぶりにやる。
until (a = $<.gets.split.map(&:to_i)) == [0, 0] h, w = a tiles = h.times.map {$<.gets.chomp} positions = [0] x, y = 0, 0 result = loop do case tiles[y][x] when ">" then x += 1 when "<" then x -= 1 when "^" then y -= 1 when "v" then y += 1 when "." then break "#{x} #{y}" else raise "error" end po = y * w + x break "LOOP" if positions.include?(po) positions << po end puts result end
簡単だけれどドキドキするな。
0105 Book Index
index = Hash.new([]) $<.readlines.map do |l| a = l.chomp.split [a.first, a.last.to_i] end.each {|word, page| index[word] += [page]} index.keys.sort.each {|k| puts k, index[k].sort.join(" ")}
0106 Discounts of Buckwheat
table = [[200, 380, 5, 0.8], [300, 550, 4, 0.85], [500, 850, 3, 0.88]] A, B, C = table.map(&:first) calc = ->(shop, num) { t = table[shop] discount = (num / t[2]) * t[2] discount * t[1] * t[3] + (num - discount) * t[1] } until (soba = $<.gets.to_i).zero? min = Float::INFINITY (0..soba / C).each do |c| pay = calc.(2, c) soba1 = soba - c * C (0..soba1 / B).each do |b| pay1 = pay + calc.(1, b) soba2 = soba1 - b * B next if (soba2 % A).nonzero? pay2 = pay1 + calc.(0, soba2 / A) min = pay2 if pay2 < min end end puts min.to_i end
再帰で解いた方がよかったかな。ごちゃごちゃしたコードだ。
0107 Carry a Cheese
until (a = $<.gets.split.map(&:to_i)) == [0, 0, 0] $<.gets.to_i.times.map {$<.gets.to_i}.each do |r| result = a.combination(2).map do |w, h| Math.sqrt((w / 2.0) ** 2 + (h / 2.0) ** 2) < r end.any? puts result ? "OK" : "NA" end end
0108 Operation of Frequency of Appearance
def operation(ary, prev = [], i = 0) return i - 1, ary if ary == prev count = Hash.new(0) ary.each {|x| count[x] += 1} operation(ary.map {|x| count[x]}, ary, i + 1) end until $<.gets.to_i.zero? i, ary = operation($<.gets.split.map(&:to_i)) puts i, ary.join(" ") end
0109 Smart Calculator
$<.gets.to_i.times do splited = $<.gets.chomp.scan(/([0-9\.]+|\+|\-|\*|\/|\(|\)|=)/) output = [] stack = [] a = nil until (token = splited.shift) == ["="] token = token.first case token when "(" then stack << token when ")" then output << a until (a = stack.pop) == "(" when "*", "/" loop do a = stack.last break unless %w(* /).include?(a) output << stack.pop end stack << token when "+", "-" loop do a = stack.last break unless %w(+ - * /).include?(a) output << stack.pop end stack << token else output << token end end output << a while (a = stack.pop) stack = [] while (x = output.shift) if %w(+ - * /).include?(x) a, b = stack.pop, stack.pop stack << eval("#{b} #{x} #{a}").to_i else stack << x end end puts stack.first end
何がいけないのかわからない。
どうしてもわからないので他人の回答を見た。喰らった…。
$<.gets.to_i.times do splited = $<.gets.chomp.scan(/([0-9\.]+|\+|\-|\*|\/|\(|\)|=)/) a = nil # パーサー(逆ポーランド記法に変換) output = [] stack = [] until (token = splited.shift) == ["="] token = token.first case token when "(" then stack << token when ")" then output << a until (a = stack.pop) == "(" when "*", "/" loop do a = stack.last break unless %w(* /).include?(a) output << stack.pop end stack << token when "+", "-" loop do a = stack.last break unless %w(+ - * /).include?(a) output << stack.pop end stack << token else output << token.to_r end end output << a while (a = stack.pop) # 逆ポーランド記法を処理 stack = [] while (x = output.shift) if %w(+ - * /).include?(x) a, b = stack.pop, stack.pop if x == "/" and ((a < 0) ^ (b < 0)) stack << -(b.abs / a.abs) else stack << eval("#{b.to_i} #{x} #{a.to_i}").to_i end else stack << x end end puts stack.first.to_i end
これを見てほしい。
$ pry [1] pry(main)> -3/2 => -2
マジか! -1 ではないのか!
div はメソッド / を呼びだし、floorを取ることで計算されます。
class Numeric (Ruby 2.5.0)
やられた。そういう Ruby の仕様なのね。勉強になりました。せっかくパーサー(操車場アルゴリズム)まで書いて頑張ったのに…。なお、皆さん演算子の再定義でやっておられる。自分もそれは考えたが、それではつまらん。