/// <summary> /// Tries to parse the first line <paramref name="text"/>. /// </summary> /// <param name="text"></param> /// <param name="minionCount"></param> /// <returns></returns> private bool TryParseFirst(string text, out int minionCount) { var parts = PrepareText(text).Split(' '); minionCount = 0; if (parts.Length != 3) throw new ArgumentException(string.Format("Input line 1 must contain N X Y: {{{0}}}", text), "text"); minionCount = int.Parse(parts[0]); Spell = new ChainLightningSpell(parts[1], parts[2]); if (minionCount > 10) throw new ArgumentException(string.Format("Input line 1 must not specify more than 10 minions: {{{0}}}", text), "text"); Lines.Add(text); return true; }
/// <summary> /// Casts the <paramref name="spell"/> on a group of <paramref name="minions"/>. /// </summary> /// <param name="spell"></param> /// <param name="minions"></param> /// <returns>The number of minions actually struck.</returns> public int Cast(ChainLightningSpell spell, params Minion[] minions) { /* Will brute force compare them like this for now. Really, this sounds like a * Constraint Satisfaction Problem, close neighbor to the Knapsack problem: * i.e. fill knapsack with items within a budget. */ Minion target; do { // This is the best filtering / sorting that we can do. var remaining = (from m in minions orderby m.Health descending where !m.HasBeenStruck select m).ToArray(); // All done. if (!remaining.Any()) break; // Hold onto the last one in the event we cannot eliminate any of the minions. var last = remaining.Last(); while (remaining.Any() && remaining.First().Health > spell.Damage) remaining = remaining.Skip(1).ToArray(); // Target the first remaining one or the last one. target = remaining.FirstOrDefault() ?? last; // Keep going while we can hit a target. } while (spell.TryHit(target)); return minions.Count(m => m.IsDead); }