問題 http://mtsmfm.github.io/2016/08/06/doukaku-e06.html
実装リンク集 http://qiita.com/mtsmfm/items/7a0bfd2ac5b7674ce8c7
です。
45分ぐらいで解けました。
ruby の実装はまだ汚いけどこんな感じ。(ちょっときれいにした)
Monster = Struct.new( :hp, :col, :lv )
# b が a をなぐる場合のダメージ
def damage( a, b )
return 1 if "RGBRGB".index(a+b)
return 4 if "RGBRGB".index(b+a)
return 2
end
# b が a をなぐる
def hit( a, b )
return if b[0]<=0
a[0] = [0, a[0] - damage(a.col, b.col) ].max
end
# a と b が同時に殴りあう
def simhit( a, b )
a.hp = [0, a.hp - damage(a.col, b.col) ].max
b.hp = [0, b.hp - damage(b.col, a.col) ].max
end
# モンスター a と モンスターb で一度ずつ殴りあう
def fight( a, b )
case a.lv<=>b.lv
when 1
hit( b, a )
hit( a, b )
when -1
hit( a, b )
hit( b, a )
when 0
simhit( a, b )
end
end
# デッキa と デッキb で戦う
def battle( a, b )
ma, mb = [a, b].map{ |x| x.chars.each_slice(2).map{ |l,c| Monster.new( l.to_i, c, l.to_i ) }}
loop do
fight( ma.first, mb.first )
ma.shift if ma.first.hp==0
mb.shift if mb.first.hp==0
return 0 if ma.empty? && mb.empty?
return -1 if mb.empty?
return 1 if ma.empty?
end
end
def solve( src )
players = src.split(",").zip( [*0..100] )
wins=[0]*players.size
players.combination(2) do |a,b|
case battle( a[0], b[0] )
when -1
wins[a[1]]-=1
when 1
wins[b[1]]-=1
end
end
wins.zip( [*1..players.size] ).sort.map(&:last).join(",")
end
$stdout.sync=true
$all_okay=true
def test( src, expected )
actual = solve( src )
p [ actual==expected ? "ok" : "**NG**", src[0,10], actual, expected ]
$all_okay &&=actual==expected
end
test("9B,3R2G,1R2B3G", "1,3,2")
test("1G", "1")
test("1G,1R,1B", "1,2,3")
test("8B,3R2G,1R2B3G", "3,1,2")
test("6G,9R7B7B", "2,1")
puts( $all_okay ? "okay" : "something wrong" )
いつもどおり、テストデータの大半は省略。
問題文にはない暗黙の仕様(?)「レベルは一桁」に依存しているところがかっこ悪い。
zip([*0..100])
の辺りもかっこ悪い。
上記2点以外はまあまあうまく書けているのではないかと思ってるけどどうだろう。
会場では damage
メソッドの中身にちょっと驚かれたんだけど、私としては普通に書いたつもり。普通でしょ?
ヒットポイントがマイナスにならないように頑張っているのは、なんとなく。ゲームを作っていた頃の記憶のせいかもしれない。
wins[n]
が正にならないのは、そのあと sort するときに便利になるようにするため。wins[n]
を正にして、sort_by
を使った方がよかったね。