PracHub
QuestionsPremiumCoachesLearningGuidesInterview Prep

Quick Overview

This question evaluates a candidate's ability to model stateful simulations and implement deterministic battle mechanics with clean data structures and object-oriented design, covering damage calculation, turn sequencing, tie-breaking rules, default multiplier handling, and comprehensive event logging.

  • hard
  • Meta
  • Coding & Algorithms
  • Machine Learning Engineer

Simulate Monster Team Battles

Company: Meta

Role: Machine Learning Engineer

Category: Coding & Algorithms

Difficulty: hard

Interview Round: Technical Screen

Design and implement a battle simulator. Data model: - `Team`: a team name and an ordered list of monsters. - `Monster`: a monster name, a type, current health points, and a list of attacks. - `Attack`: an attack name, an attack type, and base damage. - `Outcome`: the winning team and a battle log. - `type_chart`: a mapping from `(attack_type, defender_type)` to a damage multiplier. Missing entries should default to `1.0`. Battle rules: 1. Each team fights using its first alive monster according to the team's monster order. 2. The current monsters take turns attacking. Team A attacks first in each matchup. If a monster faints before its turn, it does not attack. 3. On its turn, a monster chooses the attack that causes the highest effective damage to the current opponent: `base_damage * type_multiplier`. If multiple attacks tie, choose the earliest attack in that monster's attack list. 4. Subtract damage from the defender's health, but do not let health go below zero. 5. Record every action in a battle log, including attacker, defender, chosen attack, effective damage, remaining defender health, and any fainting events. 6. When a monster faints, the next alive monster from the same team enters the battle. 7. The battle ends when one or both teams have no alive monsters. Return an `Outcome` containing the winner, which should be `team_a`, `team_b`, or `draw`, plus the full battle log. Implement clean classes or data structures for `Team`, `Monster`, `Attack`, and `Outcome`, and implement `simulate(team_a, team_b, type_chart)`.

Quick Answer: This question evaluates a candidate's ability to model stateful simulations and implement deterministic battle mechanics with clean data structures and object-oriented design, covering damage calculation, turn sequencing, tie-breaking rules, default multiplier handling, and comprehensive event logging.

You are given two monster teams and a type effectiveness chart. Simulate the battle exactly as described. Use nested data structures that naturally map to the following models: - Team: {'name': str, 'monsters': [Monster, ...]} - Monster: {'name': str, 'type': str, 'health': int or float, 'attacks': [Attack, ...]} - Attack: {'name': str, 'type': str, 'damage': int or float} - Outcome: {'winner': 'team_a' | 'team_b' | 'draw', 'battle_log': [event, ...]} Battle rules: 1. Each team uses its first alive monster in team order. 2. The current monsters alternate turns, and Team A always attacks first in each new matchup. 3. On its turn, a monster chooses the attack with the highest effective damage: base_damage * type_multiplier. 4. If multiple attacks tie, choose the earliest one in that monster's attack list. 5. Missing entries in type_chart default to 1.0. 6. Damage reduces the defender's health, but health cannot go below 0. 7. If a monster faints before its turn, it does not attack. 8. When a monster faints, the next alive monster from that same team enters. Team A attacks first in that new matchup. 9. The battle ends when one or both teams have no alive monsters. Return an outcome dictionary with: - 'winner': 'team_a', 'team_b', or 'draw' - 'battle_log': a list of events in order Use these event formats in the log: - Attack event: {'event': 'attack', 'attacker_team': str, 'attacker': str, 'defender_team': str, 'defender': str, 'attack': str, 'damage': float, 'defender_health': float} - Faint event: {'event': 'faint', 'team': str, 'monster': str} Monsters with health <= 0 at the start are considered already fainted and are skipped without adding an initial faint event to the log.

Constraints

  • 0 <= number of monsters in each team <= 100
  • Each monster has at least 1 attack
  • 0 <= initial health <= 10^6
  • 1 <= base attack damage <= 10^6
  • All provided type multipliers are positive finite numbers

Examples

Input: ({'name': 'Alpha', 'monsters': [{'name': 'Blaze', 'type': 'fire', 'health': 30, 'attacks': [{'name': 'Flame', 'type': 'fire', 'damage': 10}, {'name': 'Bite', 'type': 'normal', 'damage': 8}]}, {'name': 'Aqua', 'type': 'water', 'health': 25, 'attacks': [{'name': 'Splash', 'type': 'water', 'damage': 9}]}]}, {'name': 'Beta', 'monsters': [{'name': 'Leafy', 'type': 'grass', 'health': 30, 'attacks': [{'name': 'Vine', 'type': 'grass', 'damage': 7}]}, {'name': 'Rocko', 'type': 'rock', 'health': 20, 'attacks': [{'name': 'Toss', 'type': 'rock', 'damage': 6}]}]}, {('fire', 'grass'): 2.0, ('grass', 'fire'): 0.5, ('water', 'rock'): 2.0, ('rock', 'water'): 0.5, ('fire', 'rock'): 0.5})

Expected Output: {'winner': 'team_a', 'battle_log': [{'event': 'attack', 'attacker_team': 'Alpha', 'attacker': 'Blaze', 'defender_team': 'Beta', 'defender': 'Leafy', 'attack': 'Flame', 'damage': 20.0, 'defender_health': 10.0}, {'event': 'attack', 'attacker_team': 'Beta', 'attacker': 'Leafy', 'defender_team': 'Alpha', 'defender': 'Blaze', 'attack': 'Vine', 'damage': 3.5, 'defender_health': 26.5}, {'event': 'attack', 'attacker_team': 'Alpha', 'attacker': 'Blaze', 'defender_team': 'Beta', 'defender': 'Leafy', 'attack': 'Flame', 'damage': 20.0, 'defender_health': 0.0}, {'event': 'faint', 'team': 'Beta', 'monster': 'Leafy'}, {'event': 'attack', 'attacker_team': 'Alpha', 'attacker': 'Blaze', 'defender_team': 'Beta', 'defender': 'Rocko', 'attack': 'Bite', 'damage': 8.0, 'defender_health': 12.0}, {'event': 'attack', 'attacker_team': 'Beta', 'attacker': 'Rocko', 'defender_team': 'Alpha', 'defender': 'Blaze', 'attack': 'Toss', 'damage': 6.0, 'defender_health': 20.5}, {'event': 'attack', 'attacker_team': 'Alpha', 'attacker': 'Blaze', 'defender_team': 'Beta', 'defender': 'Rocko', 'attack': 'Bite', 'damage': 8.0, 'defender_health': 4.0}, {'event': 'attack', 'attacker_team': 'Beta', 'attacker': 'Rocko', 'defender_team': 'Alpha', 'defender': 'Blaze', 'attack': 'Toss', 'damage': 6.0, 'defender_health': 14.5}, {'event': 'attack', 'attacker_team': 'Alpha', 'attacker': 'Blaze', 'defender_team': 'Beta', 'defender': 'Rocko', 'attack': 'Bite', 'damage': 8.0, 'defender_health': 0.0}, {'event': 'faint', 'team': 'Beta', 'monster': 'Rocko'}]}

Explanation: Blaze uses Flame against Leafy because of the 2.0 fire-vs-grass multiplier. After Leafy faints, Blaze starts the new matchup against Rocko and chooses Bite because Flame is reduced to 5.0 by the 0.5 fire-vs-rock multiplier.

Input: ({'name': 'Gamma', 'monsters': [{'name': 'Dual', 'type': 'normal', 'health': 20, 'attacks': [{'name': 'Jab', 'type': 'fire', 'damage': 10}, {'name': 'Kick', 'type': 'water', 'damage': 10}]}]}, {'name': 'Delta', 'monsters': [{'name': 'Slime', 'type': 'grass', 'health': 15, 'attacks': [{'name': 'Peck', 'type': 'normal', 'damage': 4}]}]}, {('fire', 'grass'): 1.0, ('water', 'grass'): 1.0})

Expected Output: {'winner': 'team_a', 'battle_log': [{'event': 'attack', 'attacker_team': 'Gamma', 'attacker': 'Dual', 'defender_team': 'Delta', 'defender': 'Slime', 'attack': 'Jab', 'damage': 10.0, 'defender_health': 5.0}, {'event': 'attack', 'attacker_team': 'Delta', 'attacker': 'Slime', 'defender_team': 'Gamma', 'defender': 'Dual', 'attack': 'Peck', 'damage': 4.0, 'defender_health': 16.0}, {'event': 'attack', 'attacker_team': 'Gamma', 'attacker': 'Dual', 'defender_team': 'Delta', 'defender': 'Slime', 'attack': 'Jab', 'damage': 10.0, 'defender_health': 0.0}, {'event': 'faint', 'team': 'Delta', 'monster': 'Slime'}]}

Explanation: Both Jab and Kick deal the same effective damage, so the simulator must choose the earlier attack in the list: Jab.

Input: ({'name': 'Epsilon', 'monsters': [{'name': 'Ghost', 'type': 'fire', 'health': 0, 'attacks': [{'name': 'Spark', 'type': 'fire', 'damage': 5}]}, {'name': 'Seed', 'type': 'grass', 'health': 12, 'attacks': [{'name': 'Needle', 'type': 'grass', 'damage': 5}]}]}, {'name': 'Zeta', 'monsters': [{'name': 'Stone', 'type': 'rock', 'health': 18, 'attacks': [{'name': 'Crash', 'type': 'rock', 'damage': 7}]}]}, {})

Expected Output: {'winner': 'team_b', 'battle_log': [{'event': 'attack', 'attacker_team': 'Epsilon', 'attacker': 'Seed', 'defender_team': 'Zeta', 'defender': 'Stone', 'attack': 'Needle', 'damage': 5.0, 'defender_health': 13.0}, {'event': 'attack', 'attacker_team': 'Zeta', 'attacker': 'Stone', 'defender_team': 'Epsilon', 'defender': 'Seed', 'attack': 'Crash', 'damage': 7.0, 'defender_health': 5.0}, {'event': 'attack', 'attacker_team': 'Epsilon', 'attacker': 'Seed', 'defender_team': 'Zeta', 'defender': 'Stone', 'attack': 'Needle', 'damage': 5.0, 'defender_health': 8.0}, {'event': 'attack', 'attacker_team': 'Zeta', 'attacker': 'Stone', 'defender_team': 'Epsilon', 'defender': 'Seed', 'attack': 'Crash', 'damage': 7.0, 'defender_health': 0.0}, {'event': 'faint', 'team': 'Epsilon', 'monster': 'Seed'}]}

Explanation: Ghost starts with 0 health, so Seed is the first alive monster. Because the type chart is empty, every multiplier defaults to 1.0.

Input: ({'name': 'VoidA', 'monsters': []}, {'name': 'VoidB', 'monsters': [{'name': 'Dormant', 'type': 'rock', 'health': 0, 'attacks': [{'name': 'Tap', 'type': 'rock', 'damage': 1}]}]}, {})

Expected Output: {'winner': 'draw', 'battle_log': []}

Explanation: Neither team has any alive monster at the start, so the result is a draw and no battle events occur.

Hints

  1. Keep a pointer to the current alive monster for each team, and advance it only when that monster's health reaches 0.
  2. For each turn, scan the attack list once to find the maximum effective damage; use '>' instead of '>=' so tied attacks keep the earliest choice.
Last updated: Jun 6, 2026

Loading coding console...

PracHub

Master your tech interviews with 7,500+ real questions from top companies.

Product

  • Questions
  • Learning Tracks
  • Interview Guides
  • Resources
  • Premium
  • For Universities
  • Student Access

Browse

  • By Company
  • By Role
  • By Category
  • Topic Hubs
  • SQL Questions
  • Compare Platforms
  • Discord Community

Support

  • support@prachub.com
  • (916) 541-4762

Legal

  • Privacy Policy
  • Terms of Service
  • About Us

© 2026 PracHub. All rights reserved.

Related Coding Questions

  • Solve Tree Columns And Maze Variants - Meta (medium)
  • Solve Tree Diameter and Palindromic Counts - Meta (medium)
  • Solve a Key-Door Corridor Maze - Meta (medium)
  • Solve Array Merge and Parentheses Cleanup - Meta (medium)
  • Solve Two Backtracking Array Problems - Meta (hard)