Skip to content

thisisujjawalbhatia/IITD_Feb26_AAIPL

Repository files navigation

{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "480066b8",
   "metadata": {},
   "source": [
    "<h1 align='center'>✨ Welcome to the AMD AI Premier League (AAIPL)! ✨</h1>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "078a566b-fa28-4a9f-8382-de6aeeacfcaf",
   "metadata": {},
   "source": [
    "<!-- <img src=\"./assets/aaipl.png\"> -->\n",
    "<img src=\"./assets/AMDAAIPL.png\">"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "09b4b3fe",
   "metadata": {},
   "source": [
    "\n",
    "---\n",
    "## Task\n",
    "You will be building:\n",
    "1.  **A question agent** that will ask $N$ puzzle-based questions based on provided [topics](./assets/topics.json).\n",
    "    - Create your model in [question_model.py](./agents/question_model.py) (it will be called by [question_agent.py](./agents/question_agent.py) for evaluation)\n",
    "    - *Your question agent must output questions in the format specified in [sample_question.json](./assets/sample_question.json)*.\n",
    "2. **An answer agent** that answers questions asked from a question agent.\n",
    "    -  Create your model in [answer_model.py](./agents/answer_model.py) (it will be called by [answer_agent.py](./agents/answer_agent.py) for evaluation)\n",
    "    -  *Your answer agent must output answers in the format specified in [sample_answer.json](./assets/sample_answer.json)*.\n",
    "---\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5ed3cfa0",
   "metadata": {},
   "source": [
    "## Instructions\n",
    "\n",
    "1. How to initiate your workstation:\n",
    "    1. Go to **dev.amd-ai-academy.com**.\n",
    "    2. Type in the Team ID and Password from your printout.\n",
    "    3. Sign in.\n",
    "1. Read through this README.ipynb for more details on the challenge.\n",
    "    - **Note:** If members of your team are working from the notebook simultaneously, please coordinate to ensure you do not overwrite each other's work.\n",
    "1. You can **only** use the models provided in `/root/.cache/huggingface/hub`.\n",
    "    - These will be *read-only* - please **copy** a model you'd like to use into the `AAIPL/hf_models` folder. Here you can edit the model.\n",
    "    - If you attempt to change the models in the original folder, you will be **immediately disqualified**.\n",
    "1. Check out our [Synthetic Data Generation and Unsloth Tutorial](./tutorial.ipynb) for training tips and tricks.\n",
    "1. Before the deadline, kindly ensure that you push your code to Github (except `hf_models`).\n",
    "    - You can use the [`git.sh`](./git.sh) script to easily push it. "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3cfd0427",
   "metadata": {},
   "source": [
    "## 📚 Table of Contents:\n",
    "- 📝 [Task](#task)\n",
    "- ⚙️ [Instructions](#instructions)\n",
    "- 🏏 [Tournament Overview](#tournament-overview)\n",
    "- 📋 [Guidelines](#guidelines)\n",
    "    - [Format](#format-overview)\n",
    "- 🛠️ [Submission](#️what-you-will-submit)\n",
    "- ⚠️ [Restrictions](#restrictions)\n",
    "- 📂 [Directory & Files overview](#directory--files-overview)\n",
    "- 🎮 [Getting started](#getting-started)\n",
    "    - 🚀 [Env Setup](#env-setup)\n",
    "    - 🤔 [Q-Agent](#q-agent)\n",
    "        - ✅ [Basic format-checks for questions from Q-agent](#basic-format-checks-for-questions-from-q-agent)\n",
    "    - 🤖 [A-agent](#a-agent)\n",
    "        - ✅ [Basic format-checks for answers from A-agent](#basic-format-checks-for-answers-from-a-agent)\n",
    "- 🏅 [Evaluation](#evaluation)\n",
    "    - 📊 [Scoring Criteria](#scoring-criteria)\n",
    "    - 🧮 [Scoring Example](#scoring-example)\n",
    "- ⏱ [Time Limit](#time-limit)\n",
    "<!-- - 🏆 [LeaderBoard UI/UX](#leaderboard-uiux) -->"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9386cb37",
   "metadata": {},
   "source": [
    "## Tournament Overview\n",
    "<!-- 🏏  -->\n",
    "* All matches in this tournament will be **1v1** knockout format where two teams, Team-A vs Team-B, will compete with their Q-agent (question agent) and A-agent (answer agent). You can think of this as a cricket match or baseball game where teams will switch sides.\n",
    "  * Before the matchups begin, there will be an **elimination round** where we will test your A-Agent against a hidden set of questions. The teams' A-Agents that scores the highest on these seeding questions will move onto the elimination stage. \n",
    "* Like in cricket, each match has two innings:\n",
    "    -   1st inning:\n",
    "        *   $N$ Question from the Q-agent (Team-A) and their corresponding $N$ answers from the A-agent (Team-B).\n",
    "        *   Q-agent score (Team-A): Say, $40$\n",
    "        *   A-agent score (Team-B): $60$\n",
    "\n",
    "    -   2nd inning:\n",
    "        *   $N$ Question from the Q-agent (Team-B) and their respective $N$ responses from the A-agent (Team-A).\n",
    "        *   Q-agent score (Team-B): Say, $70$\n",
    "        *   A-agent score (Team-A): $30$\n",
    "    -   Final Score:\n",
    "        *   Team-A score $=$ 1st inning Q-agent score $+$ 2nd inning A-agent score $= 40 + 30 = 70$\n",
    "        *   Team-B score $=$ 1st inning A-agent score $+$ 2nd inning Q-agent score $= 60 + 70 = 130$\n",
    "    -   Winner: **Team-B** with a score of $130$.\n",
    "\n",
    "For more info on how scoring is done, refer to the [scoring criteria section](#scoring-criteria).\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2deab9cf",
   "metadata": {},
   "source": [
    "## Guidelines\n",
    "<!-- 📋  -->\n",
    "\n",
    "### Format\n",
    "We will only consider responses from the Q-agent and the A-agent which follow the below format.\n",
    "\n",
    "*Note*: While having an explanation/reasoning is a plus, not having them doesn't disqualify the question or answer being correct.\n",
    "\n",
    "#### Q-Agent\n",
    "Given a topic, the Q-agent should generate questions in the specified JSON format:\n",
    "\n",
    "```json\n",
    "{\n",
    "    \"topic\": \"<Topic of the Question>\",\n",
    "    \"question\": \"<full question text>\",\n",
    "    \"choices\": [\n",
    "        \"A) <choice A text>\",\n",
    "        \"B) <choice B text>\",\n",
    "        \"C) <choice C text>\",\n",
    "        \"D) <choice D text>\"\n",
    "    ],\n",
    "    \"answer\": \"<correct choice letter only>\",\n",
    "    \"explanation\": \"brief explanation within 100 words for why the answer is correct\"\n",
    "}\n",
    "```\n",
    "\n",
    "The **\"Topic\"**, **\"Question\"**, **\"Choices\"**, and **\"Answer\"** will be verified for correctness.\n",
    "\n",
    "#### A-Agent\n",
    "Given a Question and Choices, A-agent should produce answer in the format of:\n",
    "\n",
    "```json\n",
    "{\n",
    "    \"answer\": \"<correct choice letter only>\",\n",
    "    \"reasoning\": \"brief reasoning within 100 words for why the answer is correct\"\n",
    "}\n",
    "```\n",
    "\n",
    "The **\"Answer\"** key will be compared with **\"Answer\"** from the opponent's Q-agent.\n",
    "\n",
    "**<u>Note</u>**: *Once again, we will **only** consider those responses from the Q-agent and the A-agent which follow the above format.*"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b858a803",
   "metadata": {},
   "source": [
    "## Submission\n",
    "<!-- 🛠️  -->\n",
    "You need to submit your code which should contain these main files:\n",
    "1. All work must be within the `AAIPL` folder. Do NOT change the folder name.\n",
    "1. No need to upload anything anywhere, we'll collect your agent code from your Jupyter Server at the end of the challenge.\n",
    "   1. The agents will be called by `python -m agents.question_agent` and `python -m agents.answer_agent`, respectively.\n",
    "1. ENSURE model checkpoint(s) (e.g., `model.safetensors` or `.pt` or `.pth`) is (are) loading and expected files are getting generated from Q-agent and A-agent, when inference is done.\n",
    "   1. Outputs must be saved to `outputs/questions.json` and `outputs/answers.json`, respectively.\n",
    "1. **<u>Note</u>: You are not required to generate any `.json` for us, we'll do that for you during evaluation setting a specific value to $N$.**\n",
    "\n",
    "You can test your submission by running the commands in the [Getting Started](#getting-started) section.\n",
    "\n",
    "<u><span style=\"color: blue\">Note</span></u>: These files will be checked for any hardcoding, RAG, or other unfair practices.<br>\n",
    "<u><span style=\"color: red\">Remarks / Caution</span></u>: A-agent is equally important as Q-agent. So, please do focus on both."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fe1cc2ce",
   "metadata": {},
   "source": [
    "## Restrictions\n",
    "<!-- ⚠️ -->\n",
    "\n",
    "1.  **<span style=\"color: red\">NO</span> LAST Minute Submission**: The submission deadline is strict. Any changes to your code after the deadline may disqualify your submission.\n",
    "1.  RAG (Retrieval Augmented Generation) techniques are not allowed.\n",
    "1.  Adversarial approaches will lead to disqualification, e.g. making A-agents hallucinate.\n",
    "1.  Usage of models other than what was provided will lead to disqualification.\n",
    "1.  Only English language is allowed for both Q-agent and A-agent.\n",
    "1.  Strictly stay within the `max_tokens` limits specified in `agen.yaml` & `qgen.yaml`. Other parameters can be changed.\n",
    "1.  Questions must pertain to the topics listed in `topics.json`.\n",
    "1.  Each question should be generated under `13 secs`. Questions exceeding this limit will not be considered.\n",
    "1.  Each answer should be generated under `9 secs`. Answers exceeding this limit will not be considered.\n",
    "\n",
    "Feel free to reach out in the Discord channel for any clarifications or questions!"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7b562cb4",
   "metadata": {},
   "source": [
    "## Directory & Files overview\n",
    "<!-- 📂  -->\n",
    "\n",
    "```plaintext\n",
    ".\n",
    "├── agents\n",
    "│   ├── question_model.py\n",
    "│   ├── question_model_llama.py (example code using Unsloth Llama)\n",
    "│   ├── question_agent.py\n",
    "│   ├── answer_model.py\n",
    "│   ├── answer_model_llama.py (example code using Unsloth Llama)\n",
    "│   └── answer_agent.py\n",
    "├── assets\n",
    "│   ├── topics_example.json # example questions w.r.t each topic\n",
    "│   ├── topics.json # Topics on which we require to generate questions\n",
    "│   ├── sample_question.json # File specifying expected format of questions generated\n",
    "│   └── sample_answer.json # Expected format of answers generated\n",
    "├── utils\n",
    "│   └── build_prompt.py # prompt-tuning scripts\n",
    "├── README.ipynb\n",
    "├── tutorial.ipynb # Synthetic Data Generation and Unsloth Tutorial\n",
    "├── tutorial_config.yaml # Config file for tutorial\n",
    "├── qgen.yaml # Generation specific parameters for Q-agent\n",
    "└── agen.yaml # Generation specific parameters for A-agent\n",
    "```\n",
    "   "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2187a198",
   "metadata": {},
   "source": [
    "## Getting started\n",
    "<!-- 🎮  -->\n",
    "Let's get started with running the Q-agent and A-agent framework.\n",
    "\n",
    "### Environment Setup\n",
    "<!-- 🚀 -->"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "62e583a6",
   "metadata": {
    "vscode": {
     "languageId": "powershell"
    }
   },
   "outputs": [],
   "source": [
    "# Import basic packages\n",
    "import json\n",
    "from typing import Dict, Any, List"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "93fdb0b0",
   "metadata": {},
   "source": [
    "### Q-Agent\n",
    "<!-- 🤔 -->\n",
    "You will update the model in `question_model.py`, which will be invoked by `question_agent.py`. In the provided skeleton, we have used the base Qwen3-4B model for Q-Agent but you should experiment with other models and techniques. Check out our [Synthetic Data Generation and Unsloth Tutorial](./tutorial.ipynb) for training tips and tricks.\n",
    "\n",
    "Generated questions must pertain to the topics mentioned in `topics.json` file. Additional topics will be added for the tournament finals.\n",
    "\n",
    "__Topics:__\n",
    "1.  `Logical Reasoning`: Syllogisms\n",
    "2.  `Puzzles`: Seating Arrangements (Linear, Circular)\n",
    "3.  `Blood Relations and Family Tree`: Puzzles involving generations and family tree logic\n",
    "4.  `Alphanumeric Series`: Mixed series questions\n",
    "\n",
    "Sample questions and answers are available in the [assets folder](./assets)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4f181848",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# Run the following code to generate questions.\n",
    "# For demo purpose, we have used the base Qwen3-4B model for Q-Agent. Participants are expected to improve upon this\n",
    "!python -m agents.question_agent \\\n",
    "    --output_file \"outputs/questions.json\" \\\n",
    "    --num_questions 20 \\\n",
    "    --verbose"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9e511c33",
   "metadata": {},
   "source": [
    "#### Basic format-checks for questions from Q-agent\n",
    "\n",
    "Generated questions must follow the [format instructions](#format-overview). All questions generated from the Q-agent will be filtered and validated before being sent to the opponent's A-agent. We generate two version of questions, one is the raw, unfiltered one `questions.json` and the other is `filtered_questions.json` after passing through the below example filter. The full filtering and validation process is part of the judging system and is not demonstrated here.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a3770ec5",
   "metadata": {},
   "outputs": [],
   "source": [
    "from transformers import AutoTokenizer\n",
    "tokenizer = AutoTokenizer.from_pretrained(\"Qwen/Qwen3-4B\", padding_side='left')\n",
    "\n",
    "def count_tokens_q(text: str) -> int:\n",
    "    \"\"\"Count the number of tokens using Qwen3-4B tokenizer\"\"\"\n",
    "    return len(tokenizer.encode(text, add_special_tokens=False))\n",
    "\n",
    "def filter_questions(questions: List[str|Dict[str, str|Any]]) -> List[Dict[str, str|Any]]:\n",
    "    def basic_checks(q2: Dict[str, str])->bool:\n",
    "        # check required keys\n",
    "        required_keys = ['topic', 'question', 'choices', 'answer']\n",
    "        if all((key in q2) for key in required_keys):\n",
    "            # check choices format\n",
    "            checks = all(isinstance(choice, str) and len(choice) > 2 and choice[0].upper() in 'ABCD' for choice in q2['choices'])\n",
    "            if isinstance(q2['choices'], list) and len(q2['choices']) == 4 and checks:\n",
    "                # check answer format\n",
    "                # Check token length\n",
    "                check_len = sum(count_tokens_q(q2[k]) for k in ['question', 'answer'])\n",
    "                check_len += sum(count_tokens_q(choice) for choice in q2['choices']) - 15\n",
    "                if check_len < 130:\n",
    "                    if check_len + count_tokens_q(q2.get('explanation', 'None')) <= 1024:\n",
    "                        # Extra Checks: (PLUS checks) len(q2['answer']) == 1 and q2['answer'].upper() in 'ABCD':\n",
    "                        if isinstance(q2['answer'], str):\n",
    "                            return True\n",
    "        return False\n",
    "    correct_format_question = []\n",
    "    for i, q in enumerate(questions):\n",
    "        if isinstance(q, dict):\n",
    "            if basic_checks(q):\n",
    "                correct_format_question.append(q)\n",
    "        elif isinstance(q, str):\n",
    "            try:\n",
    "                q1 = json.loads(q)\n",
    "                if basic_checks(q1):\n",
    "                    correct_format_question.append(q1)\n",
    "            except json.JSONDecodeError:\n",
    "                # If JSON decoding fails, skip this answer\n",
    "                print(f\"Skipping invalid JSON at index {i}: {q}\")\n",
    "                continue\n",
    "        else:\n",
    "            continue\n",
    "    if len(correct_format_question) >= 0.5 * len(questions):\n",
    "        return correct_format_question\n",
    "    return list()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8a66e521",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "with open(\"outputs/questions.json\", \"r\") as f:\n",
    "    questions = json.load(f)\n",
    "\n",
    "filtered_questions = filter_questions(questions)\n",
    "\n",
    "with open(\"outputs/filtered_questions.json\", \"w\") as f:\n",
    "    json.dump(filtered_questions, f, indent=4)\n",
    "\n",
    "print(f\"Number of questions: {len(questions)}\")\n",
    "print(f\"Number of filtered questions: {len(filtered_questions)}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8f96209d",
   "metadata": {},
   "source": [
    "### A-agent\n",
    "<!-- 🤖  -->\n",
    "You will update the model in `answer_model.py`, which will be invoked by `answer_agent.py`. In the provided skeleton, we have again used the base Qwen3-4B model for A-Agent but you should experiment with other models and techniques. Check out our [Synthetic Data Generation and Unsloth Tutorial](./tutorial.ipynb) for training tips and tricks."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d51af0a4",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# Same instructions apply for the answer agent.\n",
    "# For demo purpose, we have used the base Qwen3-4B model for A-agent. Participants are expected to improve upon this.\n",
    "!python -m agents.answer_agent \\\n",
    "    --input_file \"outputs/filtered_questions.json\" \\\n",
    "    --output_file \"outputs/answers.json\" \\\n",
    "    --verbose"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3891529b",
   "metadata": {},
   "source": [
    "#### Basic format-checks for answers from A-agent\n",
    "Generated answers must follow the [format instructions](#format-overview). The following filter is added into the `answer_agent.py`. Similar to before, two versions are saved, `answers.json` and `filtered_answers.json`. The latter is used for evaluation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3acad45e",
   "metadata": {},
   "outputs": [],
   "source": [
    "from transformers import AutoTokenizer\n",
    "tokenizer = AutoTokenizer.from_pretrained(\"Qwen/Qwen3-4B\", padding_side='left')\n",
    "\n",
    "def count_tokens_a(text: str) -> int:\n",
    "    \"\"\"Count the number of tokens in the text using the agent's tokenizer\"\"\"\n",
    "    return len(tokenizer.encode(text, add_special_tokens=False))\n",
    "\n",
    "def filter_answers(ans: List[str|Dict[str, str]]) -> List[Dict[str, str]]:\n",
    "    r\"\"\"Filter answers to ensure they are in the correct format\"\"\"\n",
    "    def basic_checks(a1: Dict[str, str])->bool:\n",
    "        # check required keys\n",
    "        required_keys = ['answer']\n",
    "        if all((key in a1) and isinstance(a1[key], str) for key in required_keys):\n",
    "            if len(a1['answer']) == 1 and (a1['answer'] not in 'ABCDabcd'):\n",
    "                    return False\n",
    "            check_len = count_tokens_a(a1['answer'])\n",
    "            if check_len < 50:\n",
    "                check_len += count_tokens_a(a1.get('reasoning', 'None'))\n",
    "                if check_len < 512:\n",
    "                    # check answer format - EXTRA checks\n",
    "                    # if len(a1['answer']) == 1 and a1['answer'].upper() in 'ABCD':\n",
    "                    return True\n",
    "        return False\n",
    "\n",
    "    filtered_answers = []\n",
    "    for i, a in enumerate(ans):\n",
    "        if isinstance(a, dict):\n",
    "            if basic_checks(a):\n",
    "                filtered_answers.append(a)\n",
    "            else:\n",
    "                filtered_answers.append(None)\n",
    "        elif isinstance(a, str):\n",
    "            # Basic checks: at least with correct JSON format\n",
    "            try:\n",
    "                a1 = json.loads(a)\n",
    "                if basic_checks(a1):\n",
    "                    filtered_answers.append(a1)\n",
    "                else:\n",
    "                    filtered_answers.append(None)\n",
    "            except json.JSONDecodeError:\n",
    "                # If JSON decoding fails, skip this answer\n",
    "                print(f\"Skipping invalid JSON at index {i}: {a}\")\n",
    "                filtered_answers.append(None)\n",
    "                continue\n",
    "        else:\n",
    "            # If the answer is neither a dict nor a str, skip it\n",
    "            print(f\"Skipping unsupported type at index {i}: {type(a)}\")\n",
    "            filtered_answers.append(None)\n",
    "    return filtered_answers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "49a4301d",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "with open(\"outputs/answers.json\", \"r\") as f:\n",
    "    answers = json.load(f)\n",
    "filtered_answers = filter_answers(answers)\n",
    "\n",
    "\n",
    "print(f\"Number of answers: {len(answers)}\")\n",
    "print(f\"Number of filtered answers: {len(filtered_answers)}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "79a6a911",
   "metadata": {},
   "source": [
    "## Evaluation\n",
    "<!-- 🏅  -->"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f2aa2284",
   "metadata": {},
   "source": [
    "### Scoring Criteria\n",
    "\n",
    "<!-- 📊  -->\n",
    "\n",
    "Scores are assigned based on: out of $N$ questions from Q-agent, how many an A-agent can answer and vice-versa. *No negative marking for wrong answers.*\n",
    "\n",
    "$$\\text{A-agent Score} = \\dfrac{\\#\\ \\text{of questions correctly answered with expected format}}{N}\\times 100$$\n",
    "$$\\text{Q-agent Score} = \\dfrac{\\#\\ \\text{of questions incorrectly answered by A-agent}}{N}\\times 100$$\n",
    "\n",
    "\n",
    "$N$ denotes the number of filtered / format-correct questions. **Teams whose Q-agent fails to generate at least $50\\%$ of `num_questions` (where `num_questions` ranges from $2$ to $1000+$) of the questions correctly (as per [format-checking](#format-overview)) will be automatically disqualified.**<br>\n",
    "\n",
    "In case of **TIE**, closed benchmark questions will be used to evaluate the answer agents (A-agent) and rank the teams accordingly.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ba1f7ccf",
   "metadata": {},
   "source": [
    "### Scoring Example"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "57c11592",
   "metadata": {},
   "outputs": [],
   "source": [
    "# calculate scores...\n",
    "N = len(filtered_questions)\n",
    "assert N == len(filtered_answers), \"Number of questions and answers must match.\"\n",
    "num_correct_answers = len([1 for q,a in zip(filtered_questions, filtered_answers) if a is not None and q['answer'] == a['answer']])\n",
    "\n",
    "# Here the answer may be correct, but since q['answer'] is not an option letter is not there, we face problems\n",
    "# Below shown is one way of simple string parsing\n",
    "num_correct_answers = len([1 for q,a in zip(filtered_questions, filtered_answers) if a is not None and q['answer'][0] == a['answer']])\n",
    "\n",
    "a_score = num_correct_answers*100/(N+1e-9)\n",
    "q_score = (N-num_correct_answers)*100/(N+1e-9)\n",
    "# Announce the scores\n",
    "print(f\"Number of questions: {N}\")\n",
    "print(f\"Number of correct answers: {num_correct_answers}\")\n",
    "print(\"Scores:\")\n",
    "print(f\"Team B: A-agent score: {a_score:.2f}\")\n",
    "print(f\"Team A: Q-agent score: {q_score:.2f}\")\n",
    "print(f\"Innings 1 winner: {'Team A' if q_score > a_score else 'Team B' if q_score < a_score else 'Draw'}\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors