Qiita上で「オフラインリアルタイムどう書く」というエントリをよく見かけていて、今ひとつ空気もルールも掴めていないが息抜きにオフラインリアルタイムどう書くE06 の問題を解いてみることにした。
「オフラインリアルタイムどう書く」自体のルール(制限時間や実装時の制限事項等)についてWeb上にほとんど説明がないことから半ば内輪向けのイベントなのだろうか?と感じたが、Qiita上に記載しているからにはオープンなイベントなのだろう、と勝手に理解している。
実装に掛かった所要時間は厳密には計っていないが大体40分程度だったはずである。
実装後に他の回答者のコードを読んでみたが、いささか素直に実装しすぎただろうか、と思わなくもなかった。
もっとこう、コードゴルフとまではいかないまでもトリッキーな実装をしたほうがよいのだろうか?
class Hogemon
attr_reader :level, :type, :hp
DAMAGE_TABLE = {
R: {R: 2, B: 4, G: 1},
B: {R: 1, B: 2, G: 4},
G: {R: 4, B: 1, G: 2}
}
def initialize level, type
@level = level.to_i
@type = type.to_sym
@hp = level.to_i
end
def down?
@hp <= 0
end
def defense another
@hp -= DAMAGE_TABLE[@type][another.type]
end
def heal
@hp = @level
end
end
class Player
attr_reader :entry_number
def initialize number, params
@entry_number = number
@hogemons = []
params.split("").each_slice(2) do |param|
@hogemons.push Hogemon.new *param
end
end
def heal
@hogemons.each{|h| h.heal}
end
def lost?
@hogemons.all?{|h| h.down?}
end
def choise
@hogemons.find{|h| not h.down?}
end
end
class League
def initialize params
@players = []
params.split(",").each.with_index(1) do |param, i|
@players.push Player.new i, param
end
end
def battle p1, p2
[p1, p2].each{|pl| pl.heal}
while h1 = p1.choise and h2 = p2.choise do
high, low = (h1.level < h2.level) ? [h2, h1] : [h1, h2]
low.defense high
high.defense low if not low.down? or h1.level === h2.level
end
(p1.lost? and p2.lost?) ? 0 : (p1.lost? ? p2.entry_number : p1.entry_number)
end
def start
result = @players.map{|p| [p.entry_number, 0]}.to_h
@players.combination(2) do |pair|
winner = battle *pair
result[winner] +=1 unless winner.zero?
end
result.sort{|a, b| (a[1] === b[1]) ? a[0] <=> b[0] : (a[1] * -1) <=> (b[1] * -1)}.map{|a| a[0]}.join(",")
end
end
while gets
puts League.new($_.chomp).start
end