Last active
October 24, 2024 23:02
-
-
Save gouf/140bd5c60f9ccd2616b08462be0cfb51 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 10 | |
8 2 24 40 25 42 26 | |
59 48 13 21 13 56 2 | |
5 59 7 57 5 25 24 | |
99 28 6 32 5 23 2 | |
62 24 19 11 19 7 21 | |
2 1 3 2 | |
2 1 3 2 | |
5 1 3 1 | |
5 3 1 2 | |
1 1 2 2 | |
4 2 3 1 | |
5 3 3 2 | |
2 3 3 2 | |
4 1 5 3 | |
2 3 3 2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
# 戦士 | |
# 体力があり、3つの攻撃スキルを持っている | |
class Fighter | |
attr_reader :id, :skills | |
attr_accessor :health | |
def initialize(id, health, skills) | |
@id = id | |
@health = health | |
@skills = skills | |
@current_skill = nil | |
end | |
def attack_skill(index) | |
@current_skill = skills_at(index) | |
end | |
def attack_power | |
@current_skill.attack_power | |
end | |
def attack_delay | |
@current_skill.attack_delay | |
end | |
def available_to_fight? | |
health.positive? | |
end | |
private | |
def skills_at(index) | |
special_attack! if special_attack?(index) | |
@skills.at(index - 1) | |
end | |
def special_attack?(index) | |
@skills.at(index - 1).then(&:special_attack?) | |
end | |
def special_attack! | |
@skills.each(&:obtain_buff!) | |
end | |
end | |
class Fighter | |
# 戦士が使う攻撃スキル | |
# 攻撃速度と攻撃力を持っている | |
# 攻撃速度と攻撃力がゼロの場合は、強化技を表す | |
class AttackSkill | |
ATTACK_SPEED_BUFF = -3 | |
ATTACK_POWER_BUFF = 5 | |
attr_reader :attack_delay, :attack_power | |
def initialize(attack_delay, attack_power) | |
@attack_delay = attack_delay | |
@attack_power = attack_power | |
end | |
def special_attack? | |
attack_delay.zero? && attack_power.zero? | |
end | |
# スキルを強化する | |
# 攻撃速度と攻撃力が上昇する | |
def obtain_buff! | |
return if special_attack? # 強化技自身の場合は何もしない | |
@attack_delay += ATTACK_SPEED_BUFF | |
@attack_power += ATTACK_POWER_BUFF | |
@attack_delay = 1 if @attack_delay <= 0 # 攻撃速度が速くなりすぎないように補正を入れる | |
end | |
end | |
end | |
# 戦闘ステージ | |
# 体力の続く限り、戦士同士を戦わせて、最後に生き残った戦士の数を返す | |
class FightStage | |
def initialize(fighters, attacks_rounds) | |
@fighters = fighters | |
@attack_rounds = attacks_rounds | |
end | |
def fight! | |
run_fight_loop! | |
@fighters.find_all(&:available_to_fight?).size | |
end | |
private | |
# 指定されたインデックスに対応する戦士とスキルを取得・設定する | |
def find_fighter_and_set_skill(fighter_id, skill_index) | |
fighter = @fighters.find { _1.id.eql?(fighter_id) } | |
fighter.attack_skill(skill_index) | |
fighter | |
end | |
# 戦闘に参加する2組の戦士を取得する | |
def find_fighters(attack_round) | |
attack_round.fighters.map do |fighter| | |
find_fighter_and_set_skill(*fighter) | |
end | |
end | |
def run_fight_loop! | |
@attack_rounds.each do |attack_round| | |
fighter1, fighter2 = find_fighters(attack_round) | |
# どちらかが戦闘不能の場合、なにもしない | |
next unless [fighter1, fighter2].any?(&available_to_fight?) | |
# 攻撃速度に応じて、どちらの戦士が攻撃できるかを判定する | |
# 攻撃速度が相手より優っている場合は、相手の体力を削る事が出来る | |
if fighter1.attack_delay.eql?(fighter2.attack_delay) | |
# なにもしない | |
elsif fighter1.attack_delay < fighter2.attack_delay | |
fighter2.health -= fighter1.attack_power | |
else | |
fighter1.health -= fighter2.attack_power | |
end | |
end | |
end | |
end | |
class FightStage | |
# 戦士が戦う相手とスキル、それぞれ1回戦分を保持する | |
class AttackRound | |
attr_reader :fighter1_id, :skill1_index, :fighter2_id, :skill2_index | |
def initialize(fighter1_id, skill1_index, fighter2_id, skill2_index) | |
@fighter1_id = fighter1_id | |
@skill1_index = skill1_index | |
@fighter2_id = fighter2_id | |
@skill2_index = skill2_index | |
end | |
def fighter1 | |
[@fighter1_id, @skill1_index] | |
end | |
def fighter2 | |
[@fighter2_id, @skill2_index] | |
end | |
def fighters | |
[fighter1, fighter2] | |
end | |
end | |
end | |
# メイン処理 | |
# 戦士達のステータスやスキル情報・行動取得と戦闘ステージでの戦闘を実行する | |
class Solver | |
def solve! | |
input | |
fight_stage = FightStage.new(@fighters, @attack_rounds) | |
fight_stage.fight! | |
end | |
private | |
def input | |
@number_of_fighters, @number_of_rounds = gets.chomp.split.map(&:to_i) | |
input_fighters | |
input_attack_rounds | |
end | |
def input_fighters | |
@fighters = | |
@number_of_fighters.times.map do |index| | |
health, *attack_elements = splat_fighter_params | |
attack_skills = | |
attack_elements.map do |attack_delay, attack_power| | |
Fighter::AttackSkill.new(attack_delay, attack_power) | |
end | |
Fighter.new(index + 1, health, attack_skills) | |
end | |
end | |
# 戦士達が、誰に対してどのスキルを使い、戦いを進めていくかを取得する | |
# ここでは 2人の戦士のIDと、それぞれのスキルのインデックスを取得する | |
def input_attack_rounds | |
@attack_rounds = | |
@number_of_rounds.times.map do | |
fighter1, skill1, fighter2, skill2 = gets.split.map(&:to_i) | |
FightStage::AttackRound.new(fighter1, skill1, fighter2, skill2) | |
end | |
end | |
# 戦士の体力と3つのスキルを取得する | |
def splat_fighter_params | |
health, *params = gets.split.map(&:to_i) | |
attack_delay1, attack_power1, *params = params | |
attack_delay2, attack_power2, *params = params | |
attack_delay3, attack_power3 = params | |
[ | |
health, | |
[attack_delay1, attack_power1], | |
[attack_delay2, attack_power2], | |
[attack_delay3, attack_power3] | |
] | |
end | |
end | |
solver = Solver.new | |
# | |
# ruby main.rb < input.txt | |
# | |
puts solver.solve! # => 3 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment