diff --git a/gemini/getting-started/intro_gemini_2_0_flash_thinking_mode.ipynb b/gemini/getting-started/intro_gemini_2_0_flash_thinking_mode.ipynb index dac5a871eab..1b94ba7d0a8 100644 --- a/gemini/getting-started/intro_gemini_2_0_flash_thinking_mode.ipynb +++ b/gemini/getting-started/intro_gemini_2_0_flash_thinking_mode.ipynb @@ -1,1505 +1,1476 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "sqi5B7V_Rjim" - }, - "outputs": [], - "source": [ - "# Copyright 2024 Google LLC\n", - "#\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# https://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "VyPmicX9RlZX" - }, - "source": [ - "# Getting Started with the Gemini 2.0 Flash Thinking Mode\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - "
\n", - " \n", - " \"Google
Open in Colab\n", - "
\n", - "
\n", - " \n", - " \"Google
Open in Colab Enterprise\n", - "
\n", - "
\n", - " \n", - " \"Vertex
Open in Vertex AI Workbench\n", - "
\n", - "
\n", - " \n", - " \"GitHub
View on GitHub\n", - "
\n", - "
\n", - "\n", - "
\n", - "\n", - "Share to:\n", - "\n", - "\n", - " \"LinkedIn\n", - "\n", - "\n", - "\n", - " \"Bluesky\n", - "\n", - "\n", - "\n", - " \"X\n", - "\n", - "\n", - "\n", - " \"Reddit\n", - "\n", - "\n", - "\n", - " \"Facebook\n", - "" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "8MqT58L6Rm_q" - }, - "source": [ - "| | |\n", - "|-|-|\n", - "| Author(s) | [Guillaume Vernade](https://github.com/giom-v), [Eric Dong](https://github.com/gericdong) |" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "3w14yjWnPVD-" - }, - "source": [ - "## Overview\n", - "\n", - "[Gemini 2.0 Flash Thinking Mode](https://cloud.google.com/vertex-ai/generative-ai/docs/thinking-mode), is an experimental model that explicitly showcases its thoughts. Built on the speed and performance of Gemini 2.0 Flash, this model is trained to use thoughts in a way that leads to stronger reasoning capabilities.\n", - "\n", - "This tutorial demonstrates how you can use the Gemini 2.0 Flash Thinking mode to solve the following complex tasks that require multiple rounds of strategizing and iteratively solving.\n", - "\n", - "- Example 1: Code simplification\n", - "- Example 2: Geometry problem (with image)\n", - "- Example 3: Understanding the image of a table\n", - "- Example 4: Generating question for a specific level of knowledge\n", - "- Example 5: Statistics\n", - "- Example 6: Mathematical brain teaser\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "gPiTOAHURvTM" - }, - "source": [ - "## Getting Started" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "CHRZUpfWSEpp" - }, - "source": [ - "### Install Google Gen AI SDK for Python\n" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "id": "sG3_LKsWSD3A", - "tags": [] - }, - "outputs": [ + "cells": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[33mWARNING: Ignoring invalid distribution -oogle-api-core (/opt/conda/lib/python3.10/site-packages)\u001b[0m\n", - "\u001b[33mWARNING: Ignoring invalid distribution -oogle-api-core (/opt/conda/lib/python3.10/site-packages)\u001b[0m\n", - "\u001b[33mWARNING: Ignoring invalid distribution -oogle-api-core (/opt/conda/lib/python3.10/site-packages)\u001b[0m\n", - "\u001b[33mWARNING: Ignoring invalid distribution -oogle-api-core (/opt/conda/lib/python3.10/site-packages)\u001b[0m\n", - "\u001b[33mWARNING: Ignoring invalid distribution -oogle-api-core (/opt/conda/lib/python3.10/site-packages)\u001b[0m\n", - "\u001b[33mWARNING: Ignoring invalid distribution -oogle-api-core (/opt/conda/lib/python3.10/site-packages)\u001b[0m\n", - "Note: you may need to restart the kernel to use updated packages.\n" - ] - } - ], - "source": [ - "%pip install --upgrade --quiet google-genai" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "HlMVjiAWSMNX" - }, - "source": [ - "### Authenticate your notebook environment (Colab only)\n", - "\n", - "If you are running this notebook on Google Colab, run the cell below to authenticate your environment." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "id": "12fnq4V0SNV3", - "tags": [] - }, - "outputs": [], - "source": [ - "import sys\n", - "\n", - "if \"google.colab\" in sys.modules:\n", - " from google.colab import auth\n", - "\n", - " auth.authenticate_user()" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "0Ef0zVX-X9Bg" - }, - "source": [ - "### Import libraries\n" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "id": "xBCH3hnAX9Bh", - "tags": [] - }, - "outputs": [], - "source": [ - "import os\n", - "\n", - "import IPython\n", - "from IPython.display import Markdown, display\n", - "from PIL import Image\n", - "from google import genai\n", - "from google.genai.types import Part" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "LymmEN6GSTn-" - }, - "source": [ - "### Set Google Cloud project information and create client\n", - "\n", - "To get started using Vertex AI, you must have an existing Google Cloud project and [enable the Vertex AI API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com).\n", - "\n", - "Learn more about [setting up a project and a development environment](https://cloud.google.com/vertex-ai/docs/start/cloud-environment)." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "id": "Nqwi-5ufWp_B", - "tags": [] - }, - "outputs": [], - "source": [ - "PROJECT_ID = \"[your-project-id]\" # @param {type: \"string\"}\n", - "if not PROJECT_ID or PROJECT_ID == \"[your-project-id]\":\n", - " PROJECT_ID = str(os.environ.get(\"GOOGLE_CLOUD_PROJECT\"))\n", - "\n", - "LOCATION = os.environ.get(\"GOOGLE_CLOUD_REGION\", \"us-central1\")" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "id": "T-tiytzQE0uM", - "tags": [] - }, - "outputs": [], - "source": [ - "client = genai.Client(\n", - " vertexai=True,\n", - " project=PROJECT_ID,\n", - " location=LOCATION,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "w0u6hYSleE0H" - }, - "source": [ - "## Use the Gemini 2.0 Flash Thinking Mode\n", - "\n", - "The following examples are some complex tasks of what the Gemini 2.0 Flash Thinking Mode can solve. In each of examples you can try using different models to see how this new model compares to other models. In some cases, you'll still get a good answer from other models; however, on re-runs you'll see that Gemini 2.0 Flash Thinking Mode is more consistent because of its thinking step." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "5M7EKckIYVFy" - }, - "source": [ - "### Set model ID\n", - "\n", - "See the [Google models](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models) page for more information." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "id": "-coEslfWPrxo", - "tags": [] - }, - "outputs": [], - "source": [ - "MODEL_ID = \"gemini-2.0-flash-thinking-exp-1219\" # @param {type: \"string\"}" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "IrRBg9UGC9nn" - }, - "source": [ - "### **Example 1**: Code simplification\n", - "\n", - "First, try with a simple code comprehension and simplification example." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "id": "dLhhffx2C9nn", - "tags": [] - }, - "outputs": [ + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "sqi5B7V_Rjim" + }, + "outputs": [], + "source": [ + "# Copyright 2024 Google LLC\n", + "#\n", + "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", + "# you may not use this file except in compliance with the License.\n", + "# You may obtain a copy of the License at\n", + "#\n", + "# https://www.apache.org/licenses/LICENSE-2.0\n", + "#\n", + "# Unless required by applicable law or agreed to in writing, software\n", + "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", + "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", + "# See the License for the specific language governing permissions and\n", + "# limitations under the License." + ] + }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "parts=[Part(video_metadata=None, thought=True, code_execution_result=None, executable_code=None, file_data=None, function_call=None, function_response=None, inline_data=None, text='Let\\'s break down the thought process to arrive at the simplified expressions and explanations for the given JavaScript code snippet:\\n\\n1. **Understanding the Goal:** The primary goal is simplification. This usually means making the code shorter, easier to read, and potentially more performant (though performance differences here are likely negligible). We need to maintain the *same mathematical outcome*.\\n\\n2. **Deconstructing the Original Expression:** The first step is to understand what each part of the expression does:\\n\\n * `radius / pixelsPerMile`: This performs a division. Let\\'s call the result of this `intermediateValue1`.\\n * `intermediateValue1 * 10`: This multiplies the result by 10.\\n * `Math.round(...)`: This rounds the multiplied value to the nearest integer.\\n * `/ 10`: This divides the rounded value by 10.\\n * `.toFixed(1)`: This formats the final result to have one digit after the decimal point.\\n\\n3. **Identifying Redundancy and Combining Operations:** Notice the multiplication by 10 followed by division by 10. These operations are inverse and *almost* cancel each other out. The `Math.round()` operation is the key reason they don\\'t completely cancel. The multiplication by 10 shifts the decimal place to the right, allowing `Math.round()` to effectively round to the nearest tenth. The subsequent division by 10 shifts the decimal back.\\n\\n4. **Initial Simplification Idea:** The core rounding logic can be expressed more concisely. Instead of multiplying by 10, rounding, and then dividing by 10, we can round to one decimal place directly. JavaScript doesn\\'t have a built-in function for rounding to a specific decimal place directly. However, we can achieve this with a slightly different approach involving multiplication and `Math.round`.\\n\\n5. **Exploring `Math.round()` with Multiplication:** If we want to round to the nearest tenth, we can multiply by 10, round to the nearest integer, and then divide by 10. This is precisely what the original code does.\\n\\n6. **Considering Alternatives to `toFixed()`:** The `.toFixed(1)` part is about formatting. Is there a way to achieve similar formatting with other methods?\\n\\n7. **Simplification Attempt 1 (Focus on Rounding):** Let\\'s combine the multiplication and division steps. Instead of two separate operations, we can do it within the `Math.round()`:\\n\\n ```javascript\\n Math.round((radius / pixelsPerMile) * 10) / 10\\n ```\\n\\n This is the same as the original mathematically but slightly more concise in terms of nested parentheses.\\n\\n8. **Simplification Attempt 2 (Direct Rounding Logic):** We can express the \"round to one decimal place\" logic directly. Multiplying by 10, rounding, and dividing by 10 achieves this.\\n\\n9. **Simplification Attempt 3 (Formatting Focus):** What if we change the order of operations? Can we round *after* the division? No, because we need to round to the nearest tenth of the result of the division.\\n\\n10. **Realizing the Core Logic:** The key is that `Math.round(x * 10) / 10` is a common pattern for rounding to one decimal place.\\n\\n11. **Exploring Alternatives to `toFixed()` for Formatting:**\\n\\n * **String Interpolation:** Template literals can be used for formatting: `` `${(Math.round(radius / pixelsPerMile * 10) / 10)}` ``. However, this might not guarantee exactly one decimal place if the result is a whole number.\\n\\n * **`Number.prototype.toLocaleString()`:** This is for internationalization and can be used for formatting, but it\\'s overkill for this specific case.\\n\\n12. **Recognizing the Value of `toFixed()`:** `.toFixed(1)` guarantees exactly one decimal place, which might be the specific requirement. If this guarantee isn\\'t needed, the expression without `.toFixed(1)` is already a simplification.\\n\\n13. **Considering Edge Cases and Clarity:** Are there any edge cases where the simplified versions might behave differently? In terms of the mathematical rounding, no. However, `.toFixed(1)`\\'s behavior with trailing zeros is important to note.\\n\\n14. **Structuring the Explanation:** Organize the simplifications from minor to more significant changes. Explain the rationale behind each step and highlight the trade-offs (e.g., losing the guaranteed single decimal place). Provide clear examples.\\n\\n15. **Adding Context and Best Practices:** Explain when each simplification might be preferred and emphasize readability and maintainability.\\n\\n\\nThis systematic approach of deconstruction, identifying patterns, exploring alternatives, and considering edge cases allows us to arrive at the different simplification options and provide a comprehensive explanation.'), Part(video_metadata=None, thought=None, code_execution_result=None, executable_code=None, file_data=None, function_call=None, function_response=None, inline_data=None, text=\"This code snippet performs a calculation and then rounds the result to one decimal place. Let's break it down and see how we can simplify it.\\n\\n**Understanding the Original Code:**\\n\\n1. **`radius / pixelsPerMile`**: This calculates a value, presumably representing a distance or scale.\\n2. **`* 10`**: This multiplies the result by 10, shifting the decimal point one place to the right.\\n3. **`Math.round(...)`**: This rounds the multiplied value to the nearest whole number.\\n4. **`/ 10`**: This divides the rounded value by 10, shifting the decimal point back to its original position. Essentially, this combination of steps rounds the initial result to the nearest tenth.\\n5. **`.toFixed(1)`**: This converts the rounded number to a string, ensuring it has exactly one digit after the decimal point.\\n\\n**Possible Simplifications:**\\n\\nHere are a few ways to simplify the code, depending on your specific needs and priorities:\\n\\n**1. Minor Simplification (Combining Operations):**\\n\\nYou can combine the multiplication and division by 10 within the `Math.round()`:\\n\\n```javascript\\n(Math.round((radius / pixelsPerMile) * 10) / 10).toFixed(1);\\n```\\n\\nThis doesn't fundamentally change the logic but can be slightly more readable as it groups the rounding operation.\\n\\n**2. Removing Redundant Parentheses (if the order of operations is clear):**\\n\\nIf you are confident in the order of operations (multiplication and division have the same precedence and are evaluated from left to right), you can remove some parentheses:\\n\\n```javascript\\n(Math.round(radius / pixelsPerMile * 10) / 10).toFixed(1); // Original\\n(Math.round(radius / pixelsPerMile * 10) / 10).toFixed(1); // No change, just highlighting\\n```\\n\\nIn this specific case, the parentheses around `radius / pixelsPerMile` are necessary to ensure that division happens before multiplication.\\n\\n**3. Combining Rounding and Formatting (if you don't need the intermediate rounded number):**\\n\\nYou can achieve the same result by applying `toFixed(1)` directly after the initial division and then performing the multiplication and rounding. However, this changes the order of operations and might not be the intended logic if you need the intermediate rounded value for something else.\\n\\n**4. Using a Separate Variable for Clarity:**\\n\\nWhile not strictly a simplification in terms of code length, using a variable can improve readability:\\n\\n```javascript\\nconst rawValue = radius / pixelsPerMile;\\nconst roundedTenth = Math.round(rawValue * 10) / 10;\\nroundedTenth.toFixed(1);\\n```\\n\\nThis makes the steps more explicit.\\n\\n**5. Considering Alternatives (Less direct simplification):**\\n\\nIf you don't strictly need `Math.round` (rounding to the nearest), you could potentially use `Math.floor` or `Math.ceil` depending on the desired rounding behavior. However, this fundamentally changes the outcome and is likely not what you want given the original code.\\n\\n**Which Simplification is Best?**\\n\\nThe best simplification depends on your priorities:\\n\\n* **Readability:** Option 4 (using a separate variable) often improves readability, even if it adds a line of code.\\n* **Conciseness:** Option 1 (combining operations within `Math.round`) is slightly more concise.\\n* **Maintaining the Exact Logic:** Options 1 and 2 maintain the exact same mathematical operations and the desired rounding to one decimal place.\\n\\n**Recommended Simplification:**\\n\\nFor most cases, **keeping the code as is or applying the minor simplification (Option 1)** is often the best approach. It clearly expresses the intent of rounding to the nearest tenth and then formatting to one decimal place.\\n\\n**Example of Option 1:**\\n\\n```javascript\\nconst result = (Math.round((radius / pixelsPerMile) * 10) / 10).toFixed(1);\\n```\\n\\nThis version is slightly more compact while still being relatively easy to understand.\\n\\n**Important Note:** The `.toFixed(1)` method returns a string. If you need the result as a number, you might need to use `parseFloat()` or `Number()` to convert it back. However, if the intention is to display the value, the string format is often what you need.\\n\")] role='model'\n" - ] - } - ], - "source": [ - "my_prompt = \"\"\"How can I simplify this? \n", - "`(Math.round(radius/pixelsPerMile * 10) / 10).toFixed(1);`\n", - "\"\"\"\n", - "\n", - "response = client.models.generate_content(\n", - " model=MODEL_ID,\n", - " contents=my_prompt,\n", - ")\n", - "\n", - "print(response.candidates[0].content)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "d6cOmdVPC9nn" - }, - "source": [ - "The model response has multiple parts. While you could use `response.text` to get the full text right away, it's actually more interesting to check each of them separately when using the thinking mode.\n", - "\n", - "The first part (as in `...content.parts[0]`) is the \"inner thoughts\" of the model, that where it analyzes the problem and comes up with its strategy. Field `thought` indicates if the part is thought from the model.\n", - "\n", - "Most of the time you won't need to check the thoughts as you'll be mostly interested in the answer, but having access to them gives you a way to check where the answers come from and how the model comes up with it. It's not a black box anymore!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can first check if the part is a thought:" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "id": "c2e4f7b7cc2c", - "tags": [] - }, - "outputs": [ + "cell_type": "markdown", + "metadata": { + "id": "VyPmicX9RlZX" + }, + "source": [ + "# Getting Started with the Gemini 2.0 Flash Thinking Mode\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + "
\n", + " \n", + " \"Google
Open in Colab\n", + "
\n", + "
\n", + " \n", + " \"Google
Open in Colab Enterprise\n", + "
\n", + "
\n", + " \n", + " \"Vertex
Open in Vertex AI Workbench\n", + "
\n", + "
\n", + " \n", + " \"GitHub
View on GitHub\n", + "
\n", + "
\n", + "\n", + "
\n", + "\n", + "Share to:\n", + "\n", + "\n", + " \"LinkedIn\n", + "\n", + "\n", + "\n", + " \"Bluesky\n", + "\n", + "\n", + "\n", + " \"X\n", + "\n", + "\n", + "\n", + " \"Reddit\n", + "\n", + "\n", + "\n", + " \"Facebook\n", + "" + ] + }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(response.candidates[0].content.parts[0].thought)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And then look at the actual text of the thinking:" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "id": "OgaDQSL2C9nn", - "tags": [] - }, - "outputs": [ + "cell_type": "markdown", + "metadata": { + "id": "8MqT58L6Rm_q" + }, + "source": [ + "| | |\n", + "|-|-|\n", + "| Author(s) | [Guillaume Vernade](https://github.com/giom-v), [Eric Dong](https://github.com/gericdong) |" + ] + }, { - "data": { - "text/markdown": [ - "Let's break down the thought process to arrive at the simplified expressions and explanations for the given JavaScript code snippet:\n", - "\n", - "1. **Understanding the Goal:** The primary goal is simplification. This usually means making the code shorter, easier to read, and potentially more performant (though performance differences here are likely negligible). We need to maintain the *same mathematical outcome*.\n", - "\n", - "2. **Deconstructing the Original Expression:** The first step is to understand what each part of the expression does:\n", - "\n", - " * `radius / pixelsPerMile`: This performs a division. Let's call the result of this `intermediateValue1`.\n", - " * `intermediateValue1 * 10`: This multiplies the result by 10.\n", - " * `Math.round(...)`: This rounds the multiplied value to the nearest integer.\n", - " * `/ 10`: This divides the rounded value by 10.\n", - " * `.toFixed(1)`: This formats the final result to have one digit after the decimal point.\n", - "\n", - "3. **Identifying Redundancy and Combining Operations:** Notice the multiplication by 10 followed by division by 10. These operations are inverse and *almost* cancel each other out. The `Math.round()` operation is the key reason they don't completely cancel. The multiplication by 10 shifts the decimal place to the right, allowing `Math.round()` to effectively round to the nearest tenth. The subsequent division by 10 shifts the decimal back.\n", - "\n", - "4. **Initial Simplification Idea:** The core rounding logic can be expressed more concisely. Instead of multiplying by 10, rounding, and then dividing by 10, we can round to one decimal place directly. JavaScript doesn't have a built-in function for rounding to a specific decimal place directly. However, we can achieve this with a slightly different approach involving multiplication and `Math.round`.\n", - "\n", - "5. **Exploring `Math.round()` with Multiplication:** If we want to round to the nearest tenth, we can multiply by 10, round to the nearest integer, and then divide by 10. This is precisely what the original code does.\n", - "\n", - "6. **Considering Alternatives to `toFixed()`:** The `.toFixed(1)` part is about formatting. Is there a way to achieve similar formatting with other methods?\n", - "\n", - "7. **Simplification Attempt 1 (Focus on Rounding):** Let's combine the multiplication and division steps. Instead of two separate operations, we can do it within the `Math.round()`:\n", - "\n", - " ```javascript\n", - " Math.round((radius / pixelsPerMile) * 10) / 10\n", - " ```\n", - "\n", - " This is the same as the original mathematically but slightly more concise in terms of nested parentheses.\n", - "\n", - "8. **Simplification Attempt 2 (Direct Rounding Logic):** We can express the \"round to one decimal place\" logic directly. Multiplying by 10, rounding, and dividing by 10 achieves this.\n", - "\n", - "9. **Simplification Attempt 3 (Formatting Focus):** What if we change the order of operations? Can we round *after* the division? No, because we need to round to the nearest tenth of the result of the division.\n", - "\n", - "10. **Realizing the Core Logic:** The key is that `Math.round(x * 10) / 10` is a common pattern for rounding to one decimal place.\n", - "\n", - "11. **Exploring Alternatives to `toFixed()` for Formatting:**\n", - "\n", - " * **String Interpolation:** Template literals can be used for formatting: `` `${(Math.round(radius / pixelsPerMile * 10) / 10)}` ``. However, this might not guarantee exactly one decimal place if the result is a whole number.\n", - "\n", - " * **`Number.prototype.toLocaleString()`:** This is for internationalization and can be used for formatting, but it's overkill for this specific case.\n", - "\n", - "12. **Recognizing the Value of `toFixed()`:** `.toFixed(1)` guarantees exactly one decimal place, which might be the specific requirement. If this guarantee isn't needed, the expression without `.toFixed(1)` is already a simplification.\n", - "\n", - "13. **Considering Edge Cases and Clarity:** Are there any edge cases where the simplified versions might behave differently? In terms of the mathematical rounding, no. However, `.toFixed(1)`'s behavior with trailing zeros is important to note.\n", - "\n", - "14. **Structuring the Explanation:** Organize the simplifications from minor to more significant changes. Explain the rationale behind each step and highlight the trade-offs (e.g., losing the guaranteed single decimal place). Provide clear examples.\n", - "\n", - "15. **Adding Context and Best Practices:** Explain when each simplification might be preferred and emphasize readability and maintainability.\n", - "\n", - "\n", - "This systematic approach of deconstruction, identifying patterns, exploring alternatives, and considering edge cases allows us to arrive at the different simplification options and provide a comprehensive explanation." - ], - "text/plain": [ - "" + "cell_type": "markdown", + "metadata": { + "id": "3w14yjWnPVD-" + }, + "source": [ + "## Overview\n", + "\n", + "[Gemini 2.0 Flash Thinking Mode](https://cloud.google.com/vertex-ai/generative-ai/docs/thinking-mode), is an experimental model that explicitly showcases its thoughts. Built on the speed and performance of Gemini 2.0 Flash, this model is trained to use thoughts in a way that leads to stronger reasoning capabilities.\n", + "\n", + "This tutorial demonstrates how you can use the Gemini 2.0 Flash Thinking mode to solve the following complex tasks that require multiple rounds of strategizing and iteratively solving.\n", + "\n", + "- Example 1: Code simplification\n", + "- Example 2: Geometry problem (with image)\n", + "- Example 3: Understanding the image of a table\n", + "- Example 4: Generating question for a specific level of knowledge\n", + "- Example 5: Statistics\n", + "- Example 6: Mathematical brain teaser\n" ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "Markdown(response.candidates[0].content.parts[0].text)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "Ig6POLZnC9no" - }, - "source": [ - "Then the second part (as in `...parts[1]`) is the actual answer:" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "id": "7cbb7f5d9faf", - "tags": [] - }, - "outputs": [ + }, { - "name": "stdout", - "output_type": "stream", - "text": [ - "None\n" - ] - } - ], - "source": [ - "print(response.candidates[0].content.parts[1].thought)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And the text of the actual answer:" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": { - "id": "BJ2aYsAhC9no", - "tags": [] - }, - "outputs": [ + "cell_type": "markdown", + "metadata": { + "id": "gPiTOAHURvTM" + }, + "source": [ + "## Getting Started" + ] + }, { - "data": { - "text/markdown": [ - "This code snippet performs a calculation and then rounds the result to one decimal place. Let's break it down and see how we can simplify it.\n", - "\n", - "**Understanding the Original Code:**\n", - "\n", - "1. **`radius / pixelsPerMile`**: This calculates a value, presumably representing a distance or scale.\n", - "2. **`* 10`**: This multiplies the result by 10, shifting the decimal point one place to the right.\n", - "3. **`Math.round(...)`**: This rounds the multiplied value to the nearest whole number.\n", - "4. **`/ 10`**: This divides the rounded value by 10, shifting the decimal point back to its original position. Essentially, this combination of steps rounds the initial result to the nearest tenth.\n", - "5. **`.toFixed(1)`**: This converts the rounded number to a string, ensuring it has exactly one digit after the decimal point.\n", - "\n", - "**Possible Simplifications:**\n", - "\n", - "Here are a few ways to simplify the code, depending on your specific needs and priorities:\n", - "\n", - "**1. Minor Simplification (Combining Operations):**\n", - "\n", - "You can combine the multiplication and division by 10 within the `Math.round()`:\n", - "\n", - "```javascript\n", - "(Math.round((radius / pixelsPerMile) * 10) / 10).toFixed(1);\n", - "```\n", - "\n", - "This doesn't fundamentally change the logic but can be slightly more readable as it groups the rounding operation.\n", - "\n", - "**2. Removing Redundant Parentheses (if the order of operations is clear):**\n", - "\n", - "If you are confident in the order of operations (multiplication and division have the same precedence and are evaluated from left to right), you can remove some parentheses:\n", - "\n", - "```javascript\n", - "(Math.round(radius / pixelsPerMile * 10) / 10).toFixed(1); // Original\n", - "(Math.round(radius / pixelsPerMile * 10) / 10).toFixed(1); // No change, just highlighting\n", - "```\n", - "\n", - "In this specific case, the parentheses around `radius / pixelsPerMile` are necessary to ensure that division happens before multiplication.\n", - "\n", - "**3. Combining Rounding and Formatting (if you don't need the intermediate rounded number):**\n", - "\n", - "You can achieve the same result by applying `toFixed(1)` directly after the initial division and then performing the multiplication and rounding. However, this changes the order of operations and might not be the intended logic if you need the intermediate rounded value for something else.\n", - "\n", - "**4. Using a Separate Variable for Clarity:**\n", - "\n", - "While not strictly a simplification in terms of code length, using a variable can improve readability:\n", - "\n", - "```javascript\n", - "const rawValue = radius / pixelsPerMile;\n", - "const roundedTenth = Math.round(rawValue * 10) / 10;\n", - "roundedTenth.toFixed(1);\n", - "```\n", - "\n", - "This makes the steps more explicit.\n", - "\n", - "**5. Considering Alternatives (Less direct simplification):**\n", - "\n", - "If you don't strictly need `Math.round` (rounding to the nearest), you could potentially use `Math.floor` or `Math.ceil` depending on the desired rounding behavior. However, this fundamentally changes the outcome and is likely not what you want given the original code.\n", - "\n", - "**Which Simplification is Best?**\n", - "\n", - "The best simplification depends on your priorities:\n", - "\n", - "* **Readability:** Option 4 (using a separate variable) often improves readability, even if it adds a line of code.\n", - "* **Conciseness:** Option 1 (combining operations within `Math.round`) is slightly more concise.\n", - "* **Maintaining the Exact Logic:** Options 1 and 2 maintain the exact same mathematical operations and the desired rounding to one decimal place.\n", - "\n", - "**Recommended Simplification:**\n", - "\n", - "For most cases, **keeping the code as is or applying the minor simplification (Option 1)** is often the best approach. It clearly expresses the intent of rounding to the nearest tenth and then formatting to one decimal place.\n", - "\n", - "**Example of Option 1:**\n", - "\n", - "```javascript\n", - "const result = (Math.round((radius / pixelsPerMile) * 10) / 10).toFixed(1);\n", - "```\n", - "\n", - "This version is slightly more compact while still being relatively easy to understand.\n", - "\n", - "**Important Note:** The `.toFixed(1)` method returns a string. If you need the result as a number, you might need to use `parseFloat()` or `Number()` to convert it back. However, if the intention is to display the value, the string format is often what you need.\n" - ], - "text/plain": [ - "" + "cell_type": "markdown", + "metadata": { + "id": "CHRZUpfWSEpp" + }, + "source": [ + "### Install Google Gen AI SDK for Python\n" ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "Markdown(response.candidates[0].content.parts[1].text)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "3ZqndSMtC9no" - }, - "source": [ - "As a comparison here's what you'd get with the \"classic\" [Gemini 2.0 Flash](https://cloud.google.com/vertex-ai/generative-ai/docs/gemini-v2) model.\n", - "\n", - "Unlike thinking mode, the normal model does not articulate its thoughts and tries to answer right away which can lead to more simple answers to complex problems." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "pY1colD0C9no", - "tags": [] - }, - "outputs": [], - "source": [ - "response = client.models.generate_content(\n", - " model=\"gemini-2.0-flash-exp\",\n", - " contents=\"How can I simplify this? `(Math.round(radius/pixelsPerMile * 10) / 10).toFixed(1);`\",\n", - ")\n", - "\n", - "Markdown(response.text)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "JmxrcZPfC9no" - }, - "source": [ - "### **Example 2**: Geometry problem (with image)\n", - "\n", - "This geometry problem requires complex reasoning and is also using Gemini multimodal capabilities to read the image." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": { - "id": "8ksBfYPZC9no", - "tags": [] - }, - "outputs": [ + }, { - "data": { - "text/html": [ - "" + "cell_type": "code", + "execution_count": 1, + "metadata": { + "id": "sG3_LKsWSD3A" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[33mWARNING: Ignoring invalid distribution -oogle-api-core (/opt/conda/lib/python3.10/site-packages)\u001b[0m\n", + "\u001b[33mWARNING: Ignoring invalid distribution -oogle-api-core (/opt/conda/lib/python3.10/site-packages)\u001b[0m\n", + "\u001b[33mWARNING: Ignoring invalid distribution -oogle-api-core (/opt/conda/lib/python3.10/site-packages)\u001b[0m\n", + "\u001b[33mWARNING: Ignoring invalid distribution -oogle-api-core (/opt/conda/lib/python3.10/site-packages)\u001b[0m\n", + "\u001b[33mWARNING: Ignoring invalid distribution -oogle-api-core (/opt/conda/lib/python3.10/site-packages)\u001b[0m\n", + "\u001b[33mWARNING: Ignoring invalid distribution -oogle-api-core (/opt/conda/lib/python3.10/site-packages)\u001b[0m\n", + "Note: you may need to restart the kernel to use updated packages.\n" + ] + } ], - "text/plain": [ - "" + "source": [ + "%pip install --upgrade --quiet google-genai" ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "img_geometry = \"https://storage.googleapis.com/generativeai-downloads/images/geometry.png\"\n", - "IPython.display.Image(url=img_geometry, width=256)" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": { - "id": "80f2vzWxC9no", - "tags": [] - }, - "outputs": [ + }, + { + "cell_type": "markdown", + "metadata": { + "id": "HlMVjiAWSMNX" + }, + "source": [ + "### Authenticate your notebook environment (Colab only)\n", + "\n", + "If you are running this notebook on Google Colab, run the cell below to authenticate your environment." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "id": "12fnq4V0SNV3" + }, + "outputs": [], + "source": [ + "import sys\n", + "\n", + "if \"google.colab\" in sys.modules:\n", + " from google.colab import auth\n", + "\n", + " auth.authenticate_user()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "0Ef0zVX-X9Bg" + }, + "source": [ + "### Import libraries\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "id": "xBCH3hnAX9Bh" + }, + "outputs": [], + "source": [ + "import os\n", + "\n", + "import IPython\n", + "from IPython.display import Markdown, display\n", + "from google import genai\n", + "from google.genai.types import Part" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "LymmEN6GSTn-" + }, + "source": [ + "### Set Google Cloud project information and create client\n", + "\n", + "To get started using Vertex AI, you must have an existing Google Cloud project and [enable the Vertex AI API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com).\n", + "\n", + "Learn more about [setting up a project and a development environment](https://cloud.google.com/vertex-ai/docs/start/cloud-environment)." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "id": "Nqwi-5ufWp_B" + }, + "outputs": [], + "source": [ + "PROJECT_ID = \"[your-project-id]\" # @param {type: \"string\"}\n", + "if not PROJECT_ID or PROJECT_ID == \"[your-project-id]\":\n", + " PROJECT_ID = str(os.environ.get(\"GOOGLE_CLOUD_PROJECT\"))\n", + "\n", + "LOCATION = os.environ.get(\"GOOGLE_CLOUD_REGION\", \"us-central1\")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "id": "T-tiytzQE0uM" + }, + "outputs": [], + "source": [ + "client = genai.Client(\n", + " vertexai=True,\n", + " project=PROJECT_ID,\n", + " location=LOCATION,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "w0u6hYSleE0H" + }, + "source": [ + "## Use the Gemini 2.0 Flash Thinking Mode\n", + "\n", + "The following examples are some complex tasks of what the Gemini 2.0 Flash Thinking Mode can solve. In each of examples you can try using different models to see how this new model compares to other models. In some cases, you'll still get a good answer from other models; however, on re-runs you'll see that Gemini 2.0 Flash Thinking Mode is more consistent because of its thinking step." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "5M7EKckIYVFy" + }, + "source": [ + "### Set model ID\n", + "\n", + "See the [Google models](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models) page for more information." + ] + }, { - "data": { - "text/markdown": [ - "The overlapping region is a sector of the circle.\n", - "\n", - "From the image, we can see that:\n", - "- The triangle has two sides of length 3 meeting at a right angle.\n", - "- The circle has a radius of 3 (as indicated by the lines of length 3 from the center to the edge).\n", - "- The corner of the triangle with the two sides of length 3 is the center of the circle.\n", - "\n", - "Since the triangle has a right angle at the center of the circle, the overlapping region is a quarter of the circle.\n", - "\n", - "The area of a circle is given by the formula $A = \\pi r^2$, where $r$ is the radius.\n", - "In this case, the radius $r = 3$.\n", - "So, the area of the full circle is $A = \\pi (3)^2 = 9\\pi$.\n", - "\n", - "The overlapping region is a sector with a central angle of 90 degrees (because it's the corner of a right-angled triangle). The fraction of the circle that this sector represents is $\\frac{90}{360} = \\frac{1}{4}$.\n", - "\n", - "Therefore, the area of the overlapping region is $\\frac{1}{4}$ of the area of the circle.\n", - "Area of overlapping region = $\\frac{1}{4} \\times 9\\pi = \\frac{9}{4}\\pi$.\n", - "\n", - "Final Answer: The final answer is $\\boxed{7.0686}$" + "cell_type": "code", + "execution_count": 6, + "metadata": { + "id": "-coEslfWPrxo" + }, + "outputs": [], + "source": [ + "MODEL_ID = \"gemini-2.0-flash-thinking-exp-1219\" # @param {type: \"string\"}" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "IrRBg9UGC9nn" + }, + "source": [ + "### **Example 1**: Code simplification\n", + "\n", + "First, try with a simple code comprehension and simplification example." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "id": "dLhhffx2C9nn" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "parts=[Part(video_metadata=None, thought=True, code_execution_result=None, executable_code=None, file_data=None, function_call=None, function_response=None, inline_data=None, text='Let\\'s break down the thought process to arrive at the simplified expressions and explanations for the given JavaScript code snippet:\\n\\n1. **Understanding the Goal:** The primary goal is simplification. This usually means making the code shorter, easier to read, and potentially more performant (though performance differences here are likely negligible). We need to maintain the *same mathematical outcome*.\\n\\n2. **Deconstructing the Original Expression:** The first step is to understand what each part of the expression does:\\n\\n * `radius / pixelsPerMile`: This performs a division. Let\\'s call the result of this `intermediateValue1`.\\n * `intermediateValue1 * 10`: This multiplies the result by 10.\\n * `Math.round(...)`: This rounds the multiplied value to the nearest integer.\\n * `/ 10`: This divides the rounded value by 10.\\n * `.toFixed(1)`: This formats the final result to have one digit after the decimal point.\\n\\n3. **Identifying Redundancy and Combining Operations:** Notice the multiplication by 10 followed by division by 10. These operations are inverse and *almost* cancel each other out. The `Math.round()` operation is the key reason they don\\'t completely cancel. The multiplication by 10 shifts the decimal place to the right, allowing `Math.round()` to effectively round to the nearest tenth. The subsequent division by 10 shifts the decimal back.\\n\\n4. **Initial Simplification Idea:** The core rounding logic can be expressed more concisely. Instead of multiplying by 10, rounding, and then dividing by 10, we can round to one decimal place directly. JavaScript doesn\\'t have a built-in function for rounding to a specific decimal place directly. However, we can achieve this with a slightly different approach involving multiplication and `Math.round`.\\n\\n5. **Exploring `Math.round()` with Multiplication:** If we want to round to the nearest tenth, we can multiply by 10, round to the nearest integer, and then divide by 10. This is precisely what the original code does.\\n\\n6. **Considering Alternatives to `toFixed()`:** The `.toFixed(1)` part is about formatting. Is there a way to achieve similar formatting with other methods?\\n\\n7. **Simplification Attempt 1 (Focus on Rounding):** Let\\'s combine the multiplication and division steps. Instead of two separate operations, we can do it within the `Math.round()`:\\n\\n ```javascript\\n Math.round((radius / pixelsPerMile) * 10) / 10\\n ```\\n\\n This is the same as the original mathematically but slightly more concise in terms of nested parentheses.\\n\\n8. **Simplification Attempt 2 (Direct Rounding Logic):** We can express the \"round to one decimal place\" logic directly. Multiplying by 10, rounding, and dividing by 10 achieves this.\\n\\n9. **Simplification Attempt 3 (Formatting Focus):** What if we change the order of operations? Can we round *after* the division? No, because we need to round to the nearest tenth of the result of the division.\\n\\n10. **Realizing the Core Logic:** The key is that `Math.round(x * 10) / 10` is a common pattern for rounding to one decimal place.\\n\\n11. **Exploring Alternatives to `toFixed()` for Formatting:**\\n\\n * **String Interpolation:** Template literals can be used for formatting: `` `${(Math.round(radius / pixelsPerMile * 10) / 10)}` ``. However, this might not guarantee exactly one decimal place if the result is a whole number.\\n\\n * **`Number.prototype.toLocaleString()`:** This is for internationalization and can be used for formatting, but it\\'s overkill for this specific case.\\n\\n12. **Recognizing the Value of `toFixed()`:** `.toFixed(1)` guarantees exactly one decimal place, which might be the specific requirement. If this guarantee isn\\'t needed, the expression without `.toFixed(1)` is already a simplification.\\n\\n13. **Considering Edge Cases and Clarity:** Are there any edge cases where the simplified versions might behave differently? In terms of the mathematical rounding, no. However, `.toFixed(1)`\\'s behavior with trailing zeros is important to note.\\n\\n14. **Structuring the Explanation:** Organize the simplifications from minor to more significant changes. Explain the rationale behind each step and highlight the trade-offs (e.g., losing the guaranteed single decimal place). Provide clear examples.\\n\\n15. **Adding Context and Best Practices:** Explain when each simplification might be preferred and emphasize readability and maintainability.\\n\\n\\nThis systematic approach of deconstruction, identifying patterns, exploring alternatives, and considering edge cases allows us to arrive at the different simplification options and provide a comprehensive explanation.'), Part(video_metadata=None, thought=None, code_execution_result=None, executable_code=None, file_data=None, function_call=None, function_response=None, inline_data=None, text=\"This code snippet performs a calculation and then rounds the result to one decimal place. Let's break it down and see how we can simplify it.\\n\\n**Understanding the Original Code:**\\n\\n1. **`radius / pixelsPerMile`**: This calculates a value, presumably representing a distance or scale.\\n2. **`* 10`**: This multiplies the result by 10, shifting the decimal point one place to the right.\\n3. **`Math.round(...)`**: This rounds the multiplied value to the nearest whole number.\\n4. **`/ 10`**: This divides the rounded value by 10, shifting the decimal point back to its original position. Essentially, this combination of steps rounds the initial result to the nearest tenth.\\n5. **`.toFixed(1)`**: This converts the rounded number to a string, ensuring it has exactly one digit after the decimal point.\\n\\n**Possible Simplifications:**\\n\\nHere are a few ways to simplify the code, depending on your specific needs and priorities:\\n\\n**1. Minor Simplification (Combining Operations):**\\n\\nYou can combine the multiplication and division by 10 within the `Math.round()`:\\n\\n```javascript\\n(Math.round((radius / pixelsPerMile) * 10) / 10).toFixed(1);\\n```\\n\\nThis doesn't fundamentally change the logic but can be slightly more readable as it groups the rounding operation.\\n\\n**2. Removing Redundant Parentheses (if the order of operations is clear):**\\n\\nIf you are confident in the order of operations (multiplication and division have the same precedence and are evaluated from left to right), you can remove some parentheses:\\n\\n```javascript\\n(Math.round(radius / pixelsPerMile * 10) / 10).toFixed(1); // Original\\n(Math.round(radius / pixelsPerMile * 10) / 10).toFixed(1); // No change, just highlighting\\n```\\n\\nIn this specific case, the parentheses around `radius / pixelsPerMile` are necessary to ensure that division happens before multiplication.\\n\\n**3. Combining Rounding and Formatting (if you don't need the intermediate rounded number):**\\n\\nYou can achieve the same result by applying `toFixed(1)` directly after the initial division and then performing the multiplication and rounding. However, this changes the order of operations and might not be the intended logic if you need the intermediate rounded value for something else.\\n\\n**4. Using a Separate Variable for Clarity:**\\n\\nWhile not strictly a simplification in terms of code length, using a variable can improve readability:\\n\\n```javascript\\nconst rawValue = radius / pixelsPerMile;\\nconst roundedTenth = Math.round(rawValue * 10) / 10;\\nroundedTenth.toFixed(1);\\n```\\n\\nThis makes the steps more explicit.\\n\\n**5. Considering Alternatives (Less direct simplification):**\\n\\nIf you don't strictly need `Math.round` (rounding to the nearest), you could potentially use `Math.floor` or `Math.ceil` depending on the desired rounding behavior. However, this fundamentally changes the outcome and is likely not what you want given the original code.\\n\\n**Which Simplification is Best?**\\n\\nThe best simplification depends on your priorities:\\n\\n* **Readability:** Option 4 (using a separate variable) often improves readability, even if it adds a line of code.\\n* **Conciseness:** Option 1 (combining operations within `Math.round`) is slightly more concise.\\n* **Maintaining the Exact Logic:** Options 1 and 2 maintain the exact same mathematical operations and the desired rounding to one decimal place.\\n\\n**Recommended Simplification:**\\n\\nFor most cases, **keeping the code as is or applying the minor simplification (Option 1)** is often the best approach. It clearly expresses the intent of rounding to the nearest tenth and then formatting to one decimal place.\\n\\n**Example of Option 1:**\\n\\n```javascript\\nconst result = (Math.round((radius / pixelsPerMile) * 10) / 10).toFixed(1);\\n```\\n\\nThis version is slightly more compact while still being relatively easy to understand.\\n\\n**Important Note:** The `.toFixed(1)` method returns a string. If you need the result as a number, you might need to use `parseFloat()` or `Number()` to convert it back. However, if the intention is to display the value, the string format is often what you need.\\n\")] role='model'\n" + ] + } ], - "text/plain": [ - "" + "source": [ + "my_prompt = \"\"\"How can I simplify this? \n", + "`(Math.round(radius/pixelsPerMile * 10) / 10).toFixed(1);`\n", + "\"\"\"\n", + "\n", + "response = client.models.generate_content(\n", + " model=MODEL_ID,\n", + " contents=my_prompt,\n", + ")\n", + "\n", + "print(response.candidates[0].content)" ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "def convert_http_to_gs(uri: str) -> str:\n", - " \"\"\"\n", - " Converts the direct http URL of an image to the Cloud Storage URI format\n", - " \"\"\"\n", - " return uri.replace(\"https://storage.googleapis.com/\", \"gs://\")\n", - "\n", - "response = client.models.generate_content(\n", - " model=MODEL_ID, \n", - " contents=[\n", - " Part.from_uri(file_uri=convert_http_to_gs(img_geometry), mime_type=\"image/png\"),\n", - " \"What's the area of the overlapping region?\",\n", - " ]\n", - ")\n", - "\n", - "Markdown(response.text)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "9_WlcJZjC9np" - }, - "source": [ - "### **Example 3**: Understanding the image of a table\n", - "\n", - "Here's another example based on an image, this time the difficulty is to understand the table and add all these numbers correctly." - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": { - "id": "-G0d2an5C9np", - "tags": [] - }, - "outputs": [ + }, { - "data": { - "text/html": [ - "" + "cell_type": "markdown", + "metadata": { + "id": "d6cOmdVPC9nn" + }, + "source": [ + "The model response has multiple parts. While you could use `response.text` to get the full text right away, it's actually more interesting to check each of them separately when using the thinking mode.\n", + "\n", + "The first part (as in `...content.parts[0]`) is the \"inner thoughts\" of the model, that where it analyzes the problem and comes up with its strategy. Field `thought` indicates if the part is thought from the model.\n", + "\n", + "Most of the time you won't need to check the thoughts as you'll be mostly interested in the answer, but having access to them gives you a way to check where the answers come from and how the model comes up with it. It's not a black box anymore!" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "e26149ff6873" + }, + "source": [ + "You can first check if the part is a thought:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "id": "c2e4f7b7cc2c" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n" + ] + } ], - "text/plain": [ - "" + "source": [ + "print(response.candidates[0].content.parts[0].thought)" ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "img_table = \"https://storage.googleapis.com/generativeai-downloads/images/nfl.png\"\n", - "IPython.display.Image(url=img_table)" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": { - "id": "rexKogjfC9np", - "tags": [] - }, - "outputs": [ + }, { - "data": { - "text/markdown": [ - "Based on the projected points, the team on the **right** is projected to win this week.\n", - "\n", - "Here's the breakdown:\n", - "\n", - "* **Team on the Left:** Has a total projected score of **119.2**\n", - "* **Team on the Right:** Has a total projected score of **125.6**\n", - "\n", - "It's important to remember that these are just projections, and actual scores can vary. Good luck!\n" + "cell_type": "markdown", + "metadata": { + "id": "9048bf222994" + }, + "source": [ + "And then look at the actual text of the thinking:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "id": "OgaDQSL2C9nn" + }, + "outputs": [ + { + "data": { + "text/markdown": [ + "Let's break down the thought process to arrive at the simplified expressions and explanations for the given JavaScript code snippet:\n", + "\n", + "1. **Understanding the Goal:** The primary goal is simplification. This usually means making the code shorter, easier to read, and potentially more performant (though performance differences here are likely negligible). We need to maintain the *same mathematical outcome*.\n", + "\n", + "2. **Deconstructing the Original Expression:** The first step is to understand what each part of the expression does:\n", + "\n", + " * `radius / pixelsPerMile`: This performs a division. Let's call the result of this `intermediateValue1`.\n", + " * `intermediateValue1 * 10`: This multiplies the result by 10.\n", + " * `Math.round(...)`: This rounds the multiplied value to the nearest integer.\n", + " * `/ 10`: This divides the rounded value by 10.\n", + " * `.toFixed(1)`: This formats the final result to have one digit after the decimal point.\n", + "\n", + "3. **Identifying Redundancy and Combining Operations:** Notice the multiplication by 10 followed by division by 10. These operations are inverse and *almost* cancel each other out. The `Math.round()` operation is the key reason they don't completely cancel. The multiplication by 10 shifts the decimal place to the right, allowing `Math.round()` to effectively round to the nearest tenth. The subsequent division by 10 shifts the decimal back.\n", + "\n", + "4. **Initial Simplification Idea:** The core rounding logic can be expressed more concisely. Instead of multiplying by 10, rounding, and then dividing by 10, we can round to one decimal place directly. JavaScript doesn't have a built-in function for rounding to a specific decimal place directly. However, we can achieve this with a slightly different approach involving multiplication and `Math.round`.\n", + "\n", + "5. **Exploring `Math.round()` with Multiplication:** If we want to round to the nearest tenth, we can multiply by 10, round to the nearest integer, and then divide by 10. This is precisely what the original code does.\n", + "\n", + "6. **Considering Alternatives to `toFixed()`:** The `.toFixed(1)` part is about formatting. Is there a way to achieve similar formatting with other methods?\n", + "\n", + "7. **Simplification Attempt 1 (Focus on Rounding):** Let's combine the multiplication and division steps. Instead of two separate operations, we can do it within the `Math.round()`:\n", + "\n", + " ```javascript\n", + " Math.round((radius / pixelsPerMile) * 10) / 10\n", + " ```\n", + "\n", + " This is the same as the original mathematically but slightly more concise in terms of nested parentheses.\n", + "\n", + "8. **Simplification Attempt 2 (Direct Rounding Logic):** We can express the \"round to one decimal place\" logic directly. Multiplying by 10, rounding, and dividing by 10 achieves this.\n", + "\n", + "9. **Simplification Attempt 3 (Formatting Focus):** What if we change the order of operations? Can we round *after* the division? No, because we need to round to the nearest tenth of the result of the division.\n", + "\n", + "10. **Realizing the Core Logic:** The key is that `Math.round(x * 10) / 10` is a common pattern for rounding to one decimal place.\n", + "\n", + "11. **Exploring Alternatives to `toFixed()` for Formatting:**\n", + "\n", + " * **String Interpolation:** Template literals can be used for formatting: `` `${(Math.round(radius / pixelsPerMile * 10) / 10)}` ``. However, this might not guarantee exactly one decimal place if the result is a whole number.\n", + "\n", + " * **`Number.prototype.toLocaleString()`:** This is for internationalization and can be used for formatting, but it's overkill for this specific case.\n", + "\n", + "12. **Recognizing the Value of `toFixed()`:** `.toFixed(1)` guarantees exactly one decimal place, which might be the specific requirement. If this guarantee isn't needed, the expression without `.toFixed(1)` is already a simplification.\n", + "\n", + "13. **Considering Edge Cases and Clarity:** Are there any edge cases where the simplified versions might behave differently? In terms of the mathematical rounding, no. However, `.toFixed(1)`'s behavior with trailing zeros is important to note.\n", + "\n", + "14. **Structuring the Explanation:** Organize the simplifications from minor to more significant changes. Explain the rationale behind each step and highlight the trade-offs (e.g., losing the guaranteed single decimal place). Provide clear examples.\n", + "\n", + "15. **Adding Context and Best Practices:** Explain when each simplification might be preferred and emphasize readability and maintainability.\n", + "\n", + "\n", + "This systematic approach of deconstruction, identifying patterns, exploring alternatives, and considering edge cases allows us to arrive at the different simplification options and provide a comprehensive explanation." + ], + "text/plain": [ + "" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } ], - "text/plain": [ - "" + "source": [ + "Markdown(response.candidates[0].content.parts[0].text)" ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "response = client.models.generate_content(\n", - " model=MODEL_ID, \n", - " contents=[\n", - " Part.from_uri(file_uri=convert_http_to_gs(img_table), mime_type=\"image/png\"),\n", - " \"Who is going to win this week?\"]\n", - ")\n", - "\n", - "Markdown(response.text)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "UriRl34GC9np" - }, - "source": [ - "### **Example 4**: Generating question for a specific level of knowledge\n", - "\n", - "This time, the questions require a few types of knowledge, including what is relevant to the [Physics C: Mechanics exam](https://apcentral.collegeboard.org/courses/ap-physics-c-mechanics/exam). The questions generated are not the interesting part, but the reasoning to come up with them shows they are not just randomly generated.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": { - "id": "MU3FAUqcC9np", - "tags": [] - }, - "outputs": [ + }, { - "data": { - "text/markdown": [ - "Okay, here's a practice question you can use for the AP Physics C: Mechanics exam, focusing on a combination of concepts:\n", - "\n", - "**Question:**\n", - "\n", - "A small block of mass *m* is released from rest at the top of a frictionless ramp inclined at an angle *θ* with the horizontal. The length of the ramp is *L*. At the bottom of the ramp, the block encounters a horizontal surface with a coefficient of kinetic friction *μk*. A spring with spring constant *k* is attached to a fixed wall on this horizontal surface.\n", - "\n", - "**(a)** Derive an expression for the speed of the block as it reaches the bottom of the ramp.\n", - "\n", - "**(b)** On the horizontal surface, derive an expression for the magnitude of the acceleration of the block due to friction.\n", - "\n", - "**(c)** How much work is done by the frictional force as the block moves along the horizontal surface? Express your answer in terms of *m*, *g*, *μk*, and the distance the block travels on the horizontal surface, *d*.\n", - "\n", - "**(d)** Derive an expression for the maximum compression of the spring when the block makes contact with it. Express your answer in terms of *m*, *g*, *L*, *θ*, *μk*, and *k*.\n", - "\n", - "**(e)** Assume the block momentarily comes to rest after compressing the spring. Will the block remain at rest or will it move back along the horizontal surface? Justify your answer.\n", - "\n", - "**Tips for Using This Question:**\n", - "\n", - "* **Time yourself:** Give yourself a realistic amount of time to solve this, mimicking exam conditions.\n", - "* **Show your work:** Clearly write out all your steps and reasoning. This is crucial for getting partial credit on the actual exam.\n", - "* **Draw free-body diagrams:** This is essential for analyzing forces in parts (b) and understanding the situation in general.\n", - "* **Consider different approaches:** For some parts, there might be multiple ways to solve them (e.g., energy vs. kinematics).\n", - "* **Check your units:** Make sure your final answers have the correct units.\n", - "* **Review relevant concepts:** This question touches upon:\n", - " * **Kinematics (constant acceleration)**\n", - " * **Newton's Laws of Motion**\n", - " * **Work and Energy (potential and kinetic energy, work done by friction and springs)**\n", - " * **Conservation of Energy (with non-conservative forces)**\n", - "\n", - "**Solution Guide (Don't look until you've tried the problem!):**\n", - "\n", - "**(a)** Use conservation of energy. The potential energy at the top converts to kinetic energy at the bottom.\n", - "**(b)** Apply Newton's second law on the horizontal surface, considering the frictional force.\n", - "**(c)** Use the definition of work done by a constant force: W = F * d * cos(φ).\n", - "**(d)** Use conservation of energy again, considering the initial potential energy, work done by friction on the horizontal surface, and the potential energy stored in the spring.\n", - "**(e)** Compare the maximum static friction force with the spring force at the maximum compression point.\n", - "\n", - "This question provides a good test of your understanding of fundamental mechanics principles and your ability to apply them in a multi-step problem. Good luck! Let me know if you'd like another practice question or want to discuss the solution.\n" + "cell_type": "markdown", + "metadata": { + "id": "Ig6POLZnC9no" + }, + "source": [ + "Then the second part (as in `...parts[1]`) is the actual answer:" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "id": "7cbb7f5d9faf" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "None\n" + ] + } ], - "text/plain": [ - "" + "source": [ + "print(response.candidates[0].content.parts[1].thought)" ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "response = client.models.generate_content(\n", - " model=MODEL_ID,\n", - " contents=\"Give me a practice question I can use for the AP Physics C: Mechanics exam?\",\n", - ")\n", - "\n", - "Markdown(response.text)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "FnDwUxI-fRWo" - }, - "source": [ - "### **Example 5**: Statistics\n", - "\n", - "Here's a new mathematical problem. Once again, what's interesting is not the answer (as you might know it already) but how the model is coming up with it." - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": { - "id": "hQozYPZzgXRE", - "tags": [] - }, - "outputs": [ + }, { - "data": { - "text/markdown": [ - "### Thoughts" + "cell_type": "markdown", + "metadata": { + "id": "c8f49be520d7" + }, + "source": [ + "And the text of the actual answer:" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "id": "BJ2aYsAhC9no" + }, + "outputs": [ + { + "data": { + "text/markdown": [ + "This code snippet performs a calculation and then rounds the result to one decimal place. Let's break it down and see how we can simplify it.\n", + "\n", + "**Understanding the Original Code:**\n", + "\n", + "1. **`radius / pixelsPerMile`**: This calculates a value, presumably representing a distance or scale.\n", + "2. **`* 10`**: This multiplies the result by 10, shifting the decimal point one place to the right.\n", + "3. **`Math.round(...)`**: This rounds the multiplied value to the nearest whole number.\n", + "4. **`/ 10`**: This divides the rounded value by 10, shifting the decimal point back to its original position. Essentially, this combination of steps rounds the initial result to the nearest tenth.\n", + "5. **`.toFixed(1)`**: This converts the rounded number to a string, ensuring it has exactly one digit after the decimal point.\n", + "\n", + "**Possible Simplifications:**\n", + "\n", + "Here are a few ways to simplify the code, depending on your specific needs and priorities:\n", + "\n", + "**1. Minor Simplification (Combining Operations):**\n", + "\n", + "You can combine the multiplication and division by 10 within the `Math.round()`:\n", + "\n", + "```javascript\n", + "(Math.round((radius / pixelsPerMile) * 10) / 10).toFixed(1);\n", + "```\n", + "\n", + "This doesn't fundamentally change the logic but can be slightly more readable as it groups the rounding operation.\n", + "\n", + "**2. Removing Redundant Parentheses (if the order of operations is clear):**\n", + "\n", + "If you are confident in the order of operations (multiplication and division have the same precedence and are evaluated from left to right), you can remove some parentheses:\n", + "\n", + "```javascript\n", + "(Math.round(radius / pixelsPerMile * 10) / 10).toFixed(1); // Original\n", + "(Math.round(radius / pixelsPerMile * 10) / 10).toFixed(1); // No change, just highlighting\n", + "```\n", + "\n", + "In this specific case, the parentheses around `radius / pixelsPerMile` are necessary to ensure that division happens before multiplication.\n", + "\n", + "**3. Combining Rounding and Formatting (if you don't need the intermediate rounded number):**\n", + "\n", + "You can achieve the same result by applying `toFixed(1)` directly after the initial division and then performing the multiplication and rounding. However, this changes the order of operations and might not be the intended logic if you need the intermediate rounded value for something else.\n", + "\n", + "**4. Using a Separate Variable for Clarity:**\n", + "\n", + "While not strictly a simplification in terms of code length, using a variable can improve readability:\n", + "\n", + "```javascript\n", + "const rawValue = radius / pixelsPerMile;\n", + "const roundedTenth = Math.round(rawValue * 10) / 10;\n", + "roundedTenth.toFixed(1);\n", + "```\n", + "\n", + "This makes the steps more explicit.\n", + "\n", + "**5. Considering Alternatives (Less direct simplification):**\n", + "\n", + "If you don't strictly need `Math.round` (rounding to the nearest), you could potentially use `Math.floor` or `Math.ceil` depending on the desired rounding behavior. However, this fundamentally changes the outcome and is likely not what you want given the original code.\n", + "\n", + "**Which Simplification is Best?**\n", + "\n", + "The best simplification depends on your priorities:\n", + "\n", + "* **Readability:** Option 4 (using a separate variable) often improves readability, even if it adds a line of code.\n", + "* **Conciseness:** Option 1 (combining operations within `Math.round`) is slightly more concise.\n", + "* **Maintaining the Exact Logic:** Options 1 and 2 maintain the exact same mathematical operations and the desired rounding to one decimal place.\n", + "\n", + "**Recommended Simplification:**\n", + "\n", + "For most cases, **keeping the code as is or applying the minor simplification (Option 1)** is often the best approach. It clearly expresses the intent of rounding to the nearest tenth and then formatting to one decimal place.\n", + "\n", + "**Example of Option 1:**\n", + "\n", + "```javascript\n", + "const result = (Math.round((radius / pixelsPerMile) * 10) / 10).toFixed(1);\n", + "```\n", + "\n", + "This version is slightly more compact while still being relatively easy to understand.\n", + "\n", + "**Important Note:** The `.toFixed(1)` method returns a string. If you need the result as a number, you might need to use `parseFloat()` or `Number()` to convert it back. However, if the intention is to display the value, the string format is often what you need.\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } ], - "text/plain": [ - "" + "source": [ + "Markdown(response.candidates[0].content.parts[1].text)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "3ZqndSMtC9no" + }, + "source": [ + "As a comparison here's what you'd get with the \"classic\" [Gemini 2.0 Flash](https://cloud.google.com/vertex-ai/generative-ai/docs/gemini-v2) model.\n", + "\n", + "Unlike thinking mode, the normal model does not articulate its thoughts and tries to answer right away which can lead to more simple answers to complex problems." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "pY1colD0C9no" + }, + "outputs": [], + "source": [ + "response = client.models.generate_content(\n", + " model=\"gemini-2.0-flash-exp\",\n", + " contents=\"How can I simplify this? `(Math.round(radius/pixelsPerMile * 10) / 10).toFixed(1);`\",\n", + ")\n", + "\n", + "Markdown(response.text)" ] - }, - "metadata": {}, - "output_type": "display_data" }, { - "data": { - "text/markdown": [ - "\n", - "The problem asks for the probability of one sequence occurring before another in a series of coin flips. The two target sequences are HHH (three heads in a row) and HTH (heads, tails, heads).\n", - "\n", - "Let $P(A)$ be the probability that the sequence HHH occurs before HTH.\n", - "Let $P(B)$ be the probability that the sequence HTH occurs before HHH.\n", - "We are looking to compare $P(A)$ and $P(B)$. Since these are the only two ways the process can terminate, $P(A) + P(B) = 1$.\n", - "\n", - "We can analyze this problem using states defined by the progress towards the target sequences. The state represents the suffix of the sequence of flips that matches the beginning of either target sequence.\n", - "\n", - "States:\n", - "Start: The beginning, no flips yet.\n", - "H: The last flip was H.\n", - "HH: The last two flips were HH.\n", - "HT: The last two flips were HT.\n", - "\n", - "Absorbing states (end of the process):\n", - "HHH: Target sequence 1 reached.\n", - "HTH: Target sequence 2 reached.\n", - "\n", - "Let $p$ be the probability of flipping heads, $p = 0.5$, and $q$ be the probability of flipping tails, $q = 1 - p = 0.5$.\n", - "\n", - "Let $E_S$ be the probability that HHH occurs before HTH, starting from the Start state. This is what we want to find, $P(A) = E_S$.\n", - "Let $E_H$ be the probability that HHH occurs before HTH, given that the last flip was H.\n", - "Let $E_{HH}$ be the probability that HHH occurs before HTH, given that the last two flips were HH.\n", - "Let $E_{HT}$ be the probability that HHH occurs before HTH, given that the last two flips were HT.\n", - "\n", - "From the Start state:\n", - "If the first flip is H (prob $p$), we move to state H.\n", - "If the first flip is T (prob $q$), we remain at the Start state, as neither target sequence starts with T.\n", - "$E_S = p E_H + q E_S$\n", - "\n", - "From state H:\n", - "If the next flip is H (prob $p$), we move to state HH.\n", - "If the next flip is T (prob $q$), we move to state HT.\n", - "$E_H = p E_{HH} + q E_{HT}$\n", - "\n", - "From state HH:\n", - "If the next flip is H (prob $p$), we reach the HHH sequence, and the process stops with HHH occurring first. The probability of this event is 1.\n", - "If the next flip is T (prob $q$), we move to state HT.\n", - "$E_{HH} = p \\times 1 + q E_{HT} = p + q E_{HT}$\n", - "\n", - "From state HT:\n", - "If the next flip is H (prob $p$), we reach the HTH sequence, and the process stops with HTH occurring first. The probability of HHH occurring before HTH in this case is 0.\n", - "If the next flip is T (prob $q$), we return to the Start state, as the suffix no longer matches the beginning of either target sequence.\n", - "$E_{HT} = p \\times 0 + q E_S = q E_S$\n", - "\n", - "Now we have a system of linear equations:\n", - "1. $E_S = p E_H + q E_S$\n", - "2. $E_H = p E_{HH} + q E_{HT}$\n", - "3. $E_{HH} = p + q E_{HT}$\n", - "4. $E_{HT} = q E_S$\n", - "\n", - "Substitute equation 4 into equation 3:\n", - "$E_{HH} = p + q (q E_S) = p + q^2 E_S$\n", - "\n", - "Substitute the expression for $E_{HH}$ and equation 4 into equation 2:\n", - "$E_H = p (p + q^2 E_S) + q (q E_S) = p^2 + p q^2 E_S + q^2 E_S = p^2 + (p q^2 + q^2) E_S = p^2 + q^2 (p + 1) E_S$\n", - "\n", - "Substitute the expression for $E_H$ into equation 1:\n", - "$E_S = p (p^2 + q^2 (p + 1) E_S) + q E_S$\n", - "$E_S = p^3 + p q^2 (p + 1) E_S + q E_S$\n", - "$E_S - q E_S = p^3 + p q^2 (p + 1) E_S$\n", - "$E_S (1 - q) = p^3 + p q^2 (p + 1) E_S$\n", - "$E_S p = p^3 + p q^2 (p + 1) E_S$\n", - "\n", - "If $p \\neq 0$, we can divide by $p$:\n", - "$E_S = p^2 + q^2 (p + 1) E_S$\n", - "$E_S - q^2 (p + 1) E_S = p^2$\n", - "$E_S (1 - q^2 (p + 1)) = p^2$\n", - "\n", - "Substitute $p = 0.5$ and $q = 0.5$:\n", - "$p^2 = 0.25$\n", - "$q^2 = 0.25$\n", - "$p + 1 = 1.5$\n", - "$q^2 (p + 1) = 0.25 \\times 1.5 = 0.375$\n", - "$1 - q^2 (p + 1) = 1 - 0.375 = 0.625$\n", - "\n", - "$E_S (0.625) = 0.25$\n", - "$E_S = \\frac{0.25}{0.625} = \\frac{250}{625} = \\frac{1}{2.5} = \\frac{2}{5} = 0.4$\n", - "\n", - "So, the probability that HHH occurs before HTH is $P(A) = E_S = 0.4$.\n", - "The probability that HTH occurs before HHH is $P(B) = 1 - P(A) = 1 - 0.4 = 0.6$.\n", - "\n", - "Therefore, HTH is more likely to happen first.\n", - "\n", - "Alternative approach using expected number of flips.\n", - "\n", - "Consider the waiting times for each pattern.\n", - "Let $E_1$ be the expected number of flips until HHH appears. $E_1 = 1/p^3 = 1/(0.5)^3 = 1/0.125 = 8$.\n", - "Let $E_2$ be the expected number of flips until HTH appears.\n", - "\n", - "Consider the states and transitions for the occurrence of HTH.\n", - "Let $E_{HTH}$ be the expected number of flips to get HTH.\n", - "Starting from the beginning:\n", - "If we flip T (prob 0.5), we stay at the start.\n", - "If we flip H (prob 0.5), we are one step closer.\n", - "\n", - "Let $m = E_{HTH}$.\n", - "$m = 1 + 0.5 m + 0.5 E_H$\n", - "where $E_H$ is the expected number of additional flips needed to get HTH given the last flip was H.\n", - "\n", - "From state H:\n", - "If we flip H (prob 0.5), we go to HH.\n", - "If we flip T (prob 0.5), we go to HT.\n", - "\n", - "$E_H = 1 + 0.5 E_{HH} + 0.5 E_{HT}$\n", - "where $E_{HH}$ is the expected number of additional flips needed to get HTH given the last two flips were HH.\n", - "where $E_{HT}$ is the expected number of additional flips needed to get HTH given the last two flips were HT.\n", - "\n", - "From state HH:\n", - "If we flip H (prob 0.5), done.\n", - "If we flip T (prob 0.5), back to start.\n", - "$E_{HH} = 1 + 0.5 \\times 0 + 0.5 m = 1 + 0.5 m$\n", - "\n", - "From state HT:\n", - "If we flip H (prob 0.5), done.\n", - "If we flip T (prob 0.5), back to HT.\n", - "$E_{HT} = 1 + 0.5 \\times 0 + 0.5 E_{HT}$\n", - "$0.5 E_{HT} = 1 \\implies E_{HT} = 2$\n", - "\n", - "Substitute back:\n", - "$E_{HH} = 1 + 0.5 m$\n", - "$E_H = 1 + 0.5 (1 + 0.5 m) + 0.5 (2) = 1 + 0.5 + 0.25 m + 1 = 2.5 + 0.25 m$\n", - "$m = 1 + 0.5 m + 0.5 (2.5 + 0.25 m) = 1 + 0.5 m + 1.25 + 0.125 m$\n", - "$m = 2.25 + 0.625 m$\n", - "$m - 0.625 m = 2.25$\n", - "$0.375 m = 2.25$\n", - "$m = \\frac{2.25}{0.375} = \\frac{2250}{375} = 6$\n", - "\n", - "Expected number of flips for HTH is 10. (Error in calculation)\n", - "\n", - "Let's re-calculate expected number of flips using a different method.\n", - "\n", - "Let $E$ be the expected number of flips until the pattern occurs.\n", - "For HHH: $E = 1/p + 1/p^2 + 1/p^3 = 2 + 4 + 8 = 14$ (incorrect formula usage)\n", - "\n", - "Consider the expected waiting time for a pattern.\n", - "For a pattern $B$, let $E_B$ be the expected waiting time.\n", - "Let $S$ be the set of all finite sequences of coin flips.\n", - "Consider the events that the patterns end at time $n$.\n", - "\n", - "Gambler's Ruin Problem analogy.\n", - "\n", - "Consider the probability of HHH occurring before HTH.\n", - "Condition on the first few flips.\n", - "If the sequence starts with T, we are back to the start.\n", - "If the sequence starts with HT, then HTH will occur next.\n", - "If the sequence starts with HHT, then HHH might occur.\n", - "\n", - "Consider the first three flips:\n", - "HHH (prob 1/8) - HHH occurs\n", - "HHT (prob 1/8)\n", - "HTH (prob 1/8) - HTH occurs\n", - "HTT (prob 1/8)\n", - "THH (prob 1/8)\n", - "THT (prob 1/8)\n", - "TTH (prob 1/8)\n", - "TTT (prob 1/8)\n", - "\n", - "If the first three flips are HHH, HHH occurs first.\n", - "If the first three flips are HTH, HTH occurs first.\n", - "\n", - "Let $P$ be the probability that HHH occurs before HTH.\n", - "Condition on the first flip:\n", - "If T (prob 0.5), we start over, probability is still $P$.\n", - "If H (prob 0.5), we need to consider the next flips.\n", - "\n", - "If first flip is H:\n", - "Next flip is H (prob 0.5) -> HH\n", - "Next flip is T (prob 0.5) -> HT\n", - "\n", - "If we are at HH:\n", - "Next flip is H (prob 0.5) -> HHH (win for HHH)\n", - "Next flip is T (prob 0.5) -> HHT (restart, need to compare HHH and HTH from here)\n", - "\n", - "If we are at HT:\n", - "Next flip is H (prob 0.5) -> HTH (win for HTH)\n", - "Next flip is T (prob 0.5) -> HTT (restart)\n", - "\n", - "Let $P$ be the prob(HHH before HTH).\n", - "$P = 0.5 \\times P (\\text{HHH before HTH} | \\text{starts with T})$\n", - " $+ 0.5 \\times P (\\text{HHH before HTH} | \\text{starts with H})$\n", - "$P = 0.5 P + 0.5 P(\\text{HHH before HTH} | \\text{starts with H})$\n", - "\n", - "Let $P_H = P(\\text{HHH before HTH} | \\text{starts with H})$\n", - "Condition on the second flip:\n", - "$P_H = 0.5 P(\\text{HHH before HTH} | \\text{is HH})$\n", - " $+ 0.5 P(\\text{HHH before HTH} | \\text{is HT})$\n", - "\n", - "Let $P_{HH} = P(\\text{HHH before HTH} | \\text{is HH})$\n", - "Condition on the third flip:\n", - "$P_{HH} = 0.5 P(\\text{HHH before HTH} | \\text{is HHH}) + 0.5 P(\\text{HHH before HTH} | \\text{is HHT})$\n", - "$P_{HH} = 0.5 \\times 1 + 0.5 P_T$, where $P_T$ is the probability from start after HHT, which brings us back to comparing HHH and HTH from the start. So $P_T = P$.\n", - "$P_{HH} = 0.5 + 0.5 P$\n", - "\n", - "Let $P_{HT} = P(\\text{HHH before HTH} | \\text{is HT})$\n", - "Condition on the third flip:\n", - "$P_{HT} = 0.5 P(\\text{HHH before HTH} | \\text{is HTH}) + 0.5 P(\\text{HHH before HTH} | \\text{is HTT})$\n", - "$P_{HT} = 0.5 \\times 0 + 0.5 P = 0.5 P$\n", - "\n", - "Substitute back:\n", - "$P_H = 0.5 (0.5 + 0.5 P) + 0.5 (0.5 P) = 0.25 + 0.25 P + 0.25 P = 0.25 + 0.5 P$\n", - "\n", - "Substitute into the first equation:\n", - "$P = 0.5 P + 0.5 P_H = 0.5 P + 0.5 (0.25 + 0.5 P) = 0.5 P + 0.125 + 0.25 P$\n", - "$P = 0.75 P + 0.125$\n", - "$P - 0.75 P = 0.125$\n", - "$0.25 P = 0.125$\n", - "$P = \\frac{0.125}{0.25} = 0.5$\n", - "\n", - "Something is wrong.\n", - "\n", - "Let's use the recurrence relations approach again, carefully.\n", - "Let $E_S$ be the probability that HHH appears before HTH, starting from the empty sequence.\n", - "$E_S = p E_H + q E_T$, where $E_T = E_S$ by symmetry.\n", - "$E_S = 0.5 E_H + 0.5 E_S \\implies 0.5 E_S = 0.5 E_H \\implies E_S = E_H$. This is wrong.\n", - "\n", - "Let's use the notation from the first approach.\n", - "$P(\\text{HHH before HTH})$\n", - "\n", - "States: $\\emptyset, H, HH, HT$.\n", - "Let $P_{\\emptyset}$ be the probability starting from the beginning.\n", - "Let $P_H$ be the probability starting with H.\n", - "Let $P_{HH}$ be the probability starting with HH.\n", - "Let $P_{HT}$ be the probability starting with HT.\n", - "\n", - "$P_{\\emptyset} = 0.5 P_H + 0.5 P_{\\emptyset}$\n", - "$0.5 P_{\\emptyset} = 0.5 P_H \\implies P_{\\emptyset} = P_H$\n", - "\n", - "$P_H = 0.5 P_{HH} + 0.5 P_{HT}$\n", - "$P_{HH} = 0.5 \\times 1 + 0.5 P_{HT}$ (If next is H, HHH occurs, prob 1. If next is T, state HT)\n", - "$P_{HT} = 0.5 \\times 0 + 0.5 P_{\\emptyset}$ (If next is H, HTH occurs, prob 0. If next is T, back to start)\n", - "\n", - "Substitute $P_{HT}$:\n", - "$P_{HH} = 0.5 + 0.5 (0.5 P_{\\emptyset}) = 0.5 + 0.25 P_{\\emptyset}$\n", - "\n", - "Substitute into $P_H$:\n", - "$P_H = 0.5 (0.5 + 0.25 P_{\\emptyset}) + 0.5 (0.5 P_{\\emptyset})$\n", - "$P_H = 0.25 + 0.125 P_{\\emptyset} + 0.25 P_{\\emptyset} = 0.25 + 0.375 P_{\\emptyset}$\n", - "\n", - "Since $P_{\\emptyset} = P_H$:\n", - "$P_{\\emptyset} = 0.25 + 0.375 P_{\\emptyset}$\n", - "$P_{\\emptyset} - 0.375 P_{\\emptyset} = 0.25$\n", - "$0.625 P_{\\emptyset} = 0.25$\n", - "$P_{\\emptyset} = \\frac{0.25}{0.625} = 0.4$\n", - "\n", - "The probability that HHH occurs before HTH is 0.4.\n", - "The probability that HTH occurs before HHH is $1 - 0.4 = 0.6$.\n", - "\n", - "So HTH is more likely to happen first.\n", - "\n", - "Let's verify with a small number of flips.\n", - "Possible sequences of length 3: HHH, HHT, HTH, HTT, THH, THT, TTH, TTT (all prob 1/8).\n", - "HHH occurs first with HHH.\n", - "HTH occurs first with HTH.\n", - "If we get HHT, we continue.\n", - "If we get HTT, we continue.\n", - "If we get THH, we continue.\n", - "If we get THT, we continue.\n", - "If we get TTH, we continue.\n", - "If we get TTT, we continue.\n", - "\n", - "Consider the absorbing states.\n", - "Once we reach HHH or HTH, the process stops.\n", - "Consider paths to these states.\n", - "\n", - "Paths to HHH: HHH\n", - "Paths to HTH: HTH\n", - "\n", - "Consider sequences where the first occurrence of HHH or HTH happens at the end.\n", - "Length 3: HHH, HTH.\n", - "Length 4: THHH, CTHH (C != T), ...\n", - "Sequences ending in HHH but not containing HTH before:\n", - "THHH\n", - "Sequences ending in HTH but not containing HHH before:\n", - "THTH, HTTH (impossible), ...\n", - "\n", - "Consider the case where the process ends at the 3rd flip.\n", - "Prob(HHH) = 1/8\n", - "Prob(HTH) = 1/8\n", - "\n", - "Consider the case where the process ends at the 4th flip.\n", - "Ending with HHH: THHH (prob 1/16)\n", - "Ending with HTH: THTH (prob 1/16)\n", - "\n", - "Consider the structure of the sequences.\n", - "If HTH occurs, the preceding sequence cannot end in HH.\n", - "If HHH occurs, the preceding sequence cannot end in HT.\n", - "\n", - "Consider sequences starting with H.\n", - "HH -> HHH or HHT\n", - "HT -> HTH or HTT\n", - "\n", - "Consider runs of heads.\n", - "If we get T, we reset.\n", - "If we get H, then TH, HTH.\n", - "\n", - "Consider the first time we get HT. If the next is H, HTH occurs.\n", - "Consider the first time we get HH. If the next is H, HHH occurs.\n", - "\n", - "If the sequence starts with T, we are back to the start.\n", - "\n", - "Consider the event that HHH occurs before HTH.\n", - "This means the sequence ends with HHH, and HTH has not appeared before.\n", - "\n", - "Consider the event that HTH occurs before HHH.\n", - "This means the sequence ends with HTH, and HHH has not appeared before.\n", - "\n", - "Consider the difference between the two patterns.\n", - "HHH requires two consecutive heads before the final H.\n", - "HTH requires HT before the final H.\n", - "\n", - "If we are in state HH, the next flip determines if HHH occurs.\n", - "If we are in state HT, the next flip determines if HTH occurs.\n", - "\n", - "The problem is symmetric with respect to the outcome of flips.\n", - "The probabilities are fixed.\n", - "\n", - "Final check of the recurrence relations.\n", - "The states represent the longest suffix that is a prefix of either target sequence.\n", - "States: $\\emptyset, H, HH, HT$.\n", - "Transitions are correct.\n", - "The probabilities of moving between states are correct.\n", - "The conditions for termination are correct.\n", - "The system of equations seems correctly set up and solved.\n" + "cell_type": "markdown", + "metadata": { + "id": "JmxrcZPfC9no" + }, + "source": [ + "### **Example 2**: Geometry problem (with image)\n", + "\n", + "This geometry problem requires complex reasoning and is also using Gemini multimodal capabilities to read the image." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "id": "8ksBfYPZC9no" + }, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } ], - "text/plain": [ - "" + "source": [ + "img_geometry = (\n", + " \"https://storage.googleapis.com/generativeai-downloads/images/geometry.png\"\n", + ")\n", + "IPython.display.Image(url=img_geometry, width=256)" ] - }, - "metadata": {}, - "output_type": "display_data" }, { - "data": { - "text/markdown": [ - "### Answer" + "cell_type": "code", + "execution_count": 14, + "metadata": { + "id": "80f2vzWxC9no" + }, + "outputs": [ + { + "data": { + "text/markdown": [ + "The overlapping region is a sector of the circle.\n", + "\n", + "From the image, we can see that:\n", + "- The triangle has two sides of length 3 meeting at a right angle.\n", + "- The circle has a radius of 3 (as indicated by the lines of length 3 from the center to the edge).\n", + "- The corner of the triangle with the two sides of length 3 is the center of the circle.\n", + "\n", + "Since the triangle has a right angle at the center of the circle, the overlapping region is a quarter of the circle.\n", + "\n", + "The area of a circle is given by the formula $A = \\pi r^2$, where $r$ is the radius.\n", + "In this case, the radius $r = 3$.\n", + "So, the area of the full circle is $A = \\pi (3)^2 = 9\\pi$.\n", + "\n", + "The overlapping region is a sector with a central angle of 90 degrees (because it's the corner of a right-angled triangle). The fraction of the circle that this sector represents is $\\frac{90}{360} = \\frac{1}{4}$.\n", + "\n", + "Therefore, the area of the overlapping region is $\\frac{1}{4}$ of the area of the circle.\n", + "Area of overlapping region = $\\frac{1}{4} \\times 9\\pi = \\frac{9}{4}\\pi$.\n", + "\n", + "Final Answer: The final answer is $\\boxed{7.0686}$" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } ], - "text/plain": [ - "" + "source": [ + "def convert_http_to_gs(uri: str) -> str:\n", + " \"\"\"\n", + " Converts the direct http URL of an image to the Cloud Storage URI format\n", + " \"\"\"\n", + " return uri.replace(\"https://storage.googleapis.com/\", \"gs://\")\n", + "\n", + "\n", + "response = client.models.generate_content(\n", + " model=MODEL_ID,\n", + " contents=[\n", + " Part.from_uri(file_uri=convert_http_to_gs(img_geometry), mime_type=\"image/png\"),\n", + " \"What's the area of the overlapping region?\",\n", + " ],\n", + ")\n", + "\n", + "Markdown(response.text)" ] - }, - "metadata": {}, - "output_type": "display_data" }, { - "data": { - "text/markdown": [ - "Solution:\n", - "Let $A$ be the event that the sequence HHH occurs before the sequence HTH.\n", - "Let $B$ be the event that the sequence HTH occurs before the sequence HHH.\n", - "We want to find the probabilities of these events.\n", - "\n", - "We can use the method of conditioning on the current state of the sequence relative to the target patterns. The states are defined by the longest suffix of the current sequence that is a prefix of either HHH or HTH. The states are:\n", - "- $\\emptyset$: The starting state, no flips yet.\n", - "- H: The last flip was H.\n", - "- HH: The last two flips were HH.\n", - "- HT: The last two flips were HT.\n", - "\n", - "Let $P_S$ be the probability that HHH occurs before HTH starting from state $S$. We want to find $P_{\\emptyset}$.\n", - "\n", - "From state $\\emptyset$: $P_{\\emptyset} = 0.5 P_H + 0.5 P_{\\emptyset}$\n", - "From state H: $P_H = 0.5 P_{HH} + 0.5 P_{HT}$\n", - "From state HH: $P_{HH} = 0.5 \\times 1 + 0.5 P_{HT}$ (If next is H, HHH occurs; if next is T, go to HT)\n", - "From state HT: $P_{HT} = 0.5 \\times 0 + 0.5 P_{\\emptyset}$ (If next is H, HTH occurs; if next is T, go to $\\emptyset$)\n", - "\n", - "Substituting the expressions:\n", - "$P_{HT} = 0.5 P_{\\emptyset}$\n", - "$P_{HH} = 0.5 + 0.5 (0.5 P_{\\emptyset}) = 0.5 + 0.25 P_{\\emptyset}$\n", - "$P_H = 0.5 (0.5 + 0.25 P_{\\emptyset}) + 0.5 (0.5 P_{\\emptyset}) = 0.25 + 0.125 P_{\\emptyset} + 0.25 P_{\\emptyset} = 0.25 + 0.375 P_{\\emptyset}$\n", - "$P_{\\emptyset} = 0.5 (0.25 + 0.375 P_{\\emptyset}) + 0.5 P_{\\emptyset} = 0.125 + 0.1875 P_{\\emptyset} + 0.5 P_{\\emptyset}$\n", - "$P_{\\emptyset} = 0.125 + 0.6875 P_{\\emptyset}$\n", - "$P_{\\emptyset} (1 - 0.6875) = 0.125$\n", - "$0.3125 P_{\\emptyset} = 0.125$\n", - "$P_{\\emptyset} = \\frac{0.125}{0.3125} = \\frac{1250}{3125} = \\frac{2}{5} = 0.4$\n", - "\n", - "The probability that HHH occurs before HTH is $0.4$.\n", - "The probability that HTH occurs before HHH is $1 - 0.4 = 0.6$.\n", - "\n", - "Final Answer: The final answer is $\\boxed{HTH}$" + "cell_type": "markdown", + "metadata": { + "id": "9_WlcJZjC9np" + }, + "source": [ + "### **Example 3**: Understanding the image of a table\n", + "\n", + "Here's another example based on an image, this time the difficulty is to understand the table and add all these numbers correctly." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "id": "-G0d2an5C9np" + }, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } ], - "text/plain": [ - "" + "source": [ + "img_table = \"https://storage.googleapis.com/generativeai-downloads/images/nfl.png\"\n", + "IPython.display.Image(url=img_table)" ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "response = client.models.generate_content(\n", - " model=MODEL_ID,\n", - " contents=\"You repeatedly flipped a coin until you either flip three heads, or heads tails heads. Which is more likely to happen first?\",\n", - ")\n", - "\n", - "display(Markdown(\"### Thoughts\"))\n", - "display(Markdown(response.candidates[0].content.parts[0].text))\n", - "display(Markdown(\"### Answer\"))\n", - "display(Markdown(response.candidates[0].content.parts[1].text))" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "m9RG4DRCm1vY" - }, - "source": [ - "### **Example 6**: Mathematical brain teaser" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": { - "id": "A0_4uP5Wm6yx", - "tags": [] - }, - "outputs": [ + }, { - "data": { - "text/markdown": [ - "### Thoughts" + "cell_type": "code", + "execution_count": 16, + "metadata": { + "id": "rexKogjfC9np" + }, + "outputs": [ + { + "data": { + "text/markdown": [ + "Based on the projected points, the team on the **right** is projected to win this week.\n", + "\n", + "Here's the breakdown:\n", + "\n", + "* **Team on the Left:** Has a total projected score of **119.2**\n", + "* **Team on the Right:** Has a total projected score of **125.6**\n", + "\n", + "It's important to remember that these are just projections, and actual scores can vary. Good luck!\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } ], - "text/plain": [ - "" + "source": [ + "response = client.models.generate_content(\n", + " model=MODEL_ID,\n", + " contents=[\n", + " Part.from_uri(file_uri=convert_http_to_gs(img_table), mime_type=\"image/png\"),\n", + " \"Who is going to win this week?\",\n", + " ],\n", + ")\n", + "\n", + "Markdown(response.text)" ] - }, - "metadata": {}, - "output_type": "display_data" }, { - "data": { - "text/markdown": [ - "Here's a thought process to arrive at the solution:\n", - "\n", - "1. **Analyze the Goal and Numbers:** The target is 746. The available numbers are 8, 7, 50, and 4. Notice the target is a fairly large number, hinting that multiplication will likely be involved.\n", - "\n", - "2. **Consider the Magnitudes:** 50 is the largest number. Multiplying it by another number might get us closer to the target faster.\n", - "\n", - "3. **Initial Multiplication Ideas with 50:**\n", - " * 50 * 8 = 400 (Too small)\n", - " * 50 * 7 = 350 (Too small)\n", - " * 50 * 4 = 200 (Too small)\n", - "\n", - "4. **Combining Multiplication:** Maybe multiplying two of the smaller numbers first, then multiplying by 50 could work.\n", - " * 8 * 7 = 56. Then 56 * 50 is much larger than 746.\n", - " * 8 * 4 = 32. Then 32 * 50 is larger than 746.\n", - " * 7 * 4 = 28. Then 28 * 50 is larger than 746.\n", - "\n", - "5. **Re-evaluate the Role of 50:** Since multiplying 50 by another individual number isn't enough and multiplying it by products of the other numbers is too large, perhaps 50 should be added or subtracted later.\n", - "\n", - "6. **Focus on Getting Closer to 746 without 50 (initially):** Try combinations of 8, 7, and 4 to get a number that, when combined with 50, gets closer to 746.\n", - " * 8 * 7 = 56. What needs to be done to 56 to get near 700? Multiplying by a large number.\n", - " * 8 * 4 = 32\n", - " * 7 * 4 = 28\n", - "\n", - "7. **Consider Combining Operations:** Let's go back to multiplying 50, but consider adding or subtracting the other numbers.\n", - "\n", - "8. **Trial and Error with 50 as a Multiplier:**\n", - " * 50 * (something involving 8, 7, 4). We need the \"something\" to be roughly around 14 or 15 (746 / 50 ≈ 14.92).\n", - "\n", - "9. **Trying to get 14 or 15 with 8, 7, 4:**\n", - " * 8 + 7 - 4 = 11 (Too small)\n", - " * 8 - 7 + 4 = 5 (Too small)\n", - " * 8 * (7 - 4) = 8 * 3 = 24 (Too large)\n", - " * (8 - 7) * 4 = 1 * 4 = 4 (Too small)\n", - "\n", - "10. **Think About Getting Close to 700 with the other numbers:**\n", - " * 8 * 7 * something... no, we can only use numbers once.\n", - "\n", - "11. **Consider Using 50 as a Subtrahend:** If we get a number *larger* than 746, we could subtract 50.\n", - "\n", - "12. **Back to Multiplication with the other numbers:**\n", - " * 8 * 7 = 56. What do we need to add/multiply to get closer to 746?\n", - " * Try multiplying 50 by one of the other numbers and then adjusting.\n", - "\n", - "13. **Focus on getting a number slightly above 746:**\n", - " * 50 * something + something else.\n", - " * 50 * 8 = 400. Need to add around 346.\n", - " * 50 * 7 = 350. Need to add around 396.\n", - "\n", - "14. **Consider Multiplying Two Numbers First:**\n", - " * 50 * 8 = 400. Can we get 346 with 7 and 4? 7 * 4 = 28 (not close).\n", - " * 50 * 7 = 350. Can we get 396 with 8 and 4? 8 * 4 = 32 (not close).\n", - "\n", - "15. **Think about multiplying two numbers to get close to a factor of 746:** Not easily apparent.\n", - "\n", - "16. **Try a different arrangement of multiplication:**\n", - " * 50 * (8 + something). We need \"something\" to be small.\n", - " * 50 * (7 + something).\n", - " * 50 * (4 + something).\n", - "\n", - "17. **Consider a combination where multiplication creates a larger number, and subtraction brings it down:**\n", - " * 50 * 8 = 400. If we multiply 7 and 4 we get 28. 400 + 28 is too small.\n", - " * What if we multiply 50 by the *sum* of some numbers?\n", - "\n", - "18. **Focus on getting something close to 700:**\n", - " * 50 * (8 + 7) = 50 * 15 = 750. We're very close! Now subtract 4: 750 - 4 = 746. **Solution found!**" + "cell_type": "markdown", + "metadata": { + "id": "UriRl34GC9np" + }, + "source": [ + "### **Example 4**: Generating question for a specific level of knowledge\n", + "\n", + "This time, the questions require a few types of knowledge, including what is relevant to the [Physics C: Mechanics exam](https://apcentral.collegeboard.org/courses/ap-physics-c-mechanics/exam). The questions generated are not the interesting part, but the reasoning to come up with them shows they are not just randomly generated.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "id": "MU3FAUqcC9np" + }, + "outputs": [ + { + "data": { + "text/markdown": [ + "Okay, here's a practice question you can use for the AP Physics C: Mechanics exam, focusing on a combination of concepts:\n", + "\n", + "**Question:**\n", + "\n", + "A small block of mass *m* is released from rest at the top of a frictionless ramp inclined at an angle *θ* with the horizontal. The length of the ramp is *L*. At the bottom of the ramp, the block encounters a horizontal surface with a coefficient of kinetic friction *μk*. A spring with spring constant *k* is attached to a fixed wall on this horizontal surface.\n", + "\n", + "**(a)** Derive an expression for the speed of the block as it reaches the bottom of the ramp.\n", + "\n", + "**(b)** On the horizontal surface, derive an expression for the magnitude of the acceleration of the block due to friction.\n", + "\n", + "**(c)** How much work is done by the frictional force as the block moves along the horizontal surface? Express your answer in terms of *m*, *g*, *μk*, and the distance the block travels on the horizontal surface, *d*.\n", + "\n", + "**(d)** Derive an expression for the maximum compression of the spring when the block makes contact with it. Express your answer in terms of *m*, *g*, *L*, *θ*, *μk*, and *k*.\n", + "\n", + "**(e)** Assume the block momentarily comes to rest after compressing the spring. Will the block remain at rest or will it move back along the horizontal surface? Justify your answer.\n", + "\n", + "**Tips for Using This Question:**\n", + "\n", + "* **Time yourself:** Give yourself a realistic amount of time to solve this, mimicking exam conditions.\n", + "* **Show your work:** Clearly write out all your steps and reasoning. This is crucial for getting partial credit on the actual exam.\n", + "* **Draw free-body diagrams:** This is essential for analyzing forces in parts (b) and understanding the situation in general.\n", + "* **Consider different approaches:** For some parts, there might be multiple ways to solve them (e.g., energy vs. kinematics).\n", + "* **Check your units:** Make sure your final answers have the correct units.\n", + "* **Review relevant concepts:** This question touches upon:\n", + " * **Kinematics (constant acceleration)**\n", + " * **Newton's Laws of Motion**\n", + " * **Work and Energy (potential and kinetic energy, work done by friction and springs)**\n", + " * **Conservation of Energy (with non-conservative forces)**\n", + "\n", + "**Solution Guide (Don't look until you've tried the problem!):**\n", + "\n", + "**(a)** Use conservation of energy. The potential energy at the top converts to kinetic energy at the bottom.\n", + "**(b)** Apply Newton's second law on the horizontal surface, considering the frictional force.\n", + "**(c)** Use the definition of work done by a constant force: W = F * d * cos(φ).\n", + "**(d)** Use conservation of energy again, considering the initial potential energy, work done by friction on the horizontal surface, and the potential energy stored in the spring.\n", + "**(e)** Compare the maximum static friction force with the spring force at the maximum compression point.\n", + "\n", + "This question provides a good test of your understanding of fundamental mechanics principles and your ability to apply them in a multi-step problem. Good luck! Let me know if you'd like another practice question or want to discuss the solution.\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } ], - "text/plain": [ - "" + "source": [ + "response = client.models.generate_content(\n", + " model=MODEL_ID,\n", + " contents=\"Give me a practice question I can use for the AP Physics C: Mechanics exam?\",\n", + ")\n", + "\n", + "Markdown(response.text)" ] - }, - "metadata": {}, - "output_type": "display_data" }, { - "data": { - "text/markdown": [ - "### Answer" + "cell_type": "markdown", + "metadata": { + "id": "FnDwUxI-fRWo" + }, + "source": [ + "### **Example 5**: Statistics\n", + "\n", + "Here's a new mathematical problem. Once again, what's interesting is not the answer (as you might know it already) but how the model is coming up with it." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "id": "hQozYPZzgXRE" + }, + "outputs": [ + { + "data": { + "text/markdown": [ + "### Thoughts" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "\n", + "The problem asks for the probability of one sequence occurring before another in a series of coin flips. The two target sequences are HHH (three heads in a row) and HTH (heads, tails, heads).\n", + "\n", + "Let $P(A)$ be the probability that the sequence HHH occurs before HTH.\n", + "Let $P(B)$ be the probability that the sequence HTH occurs before HHH.\n", + "We are looking to compare $P(A)$ and $P(B)$. Since these are the only two ways the process can terminate, $P(A) + P(B) = 1$.\n", + "\n", + "We can analyze this problem using states defined by the progress towards the target sequences. The state represents the suffix of the sequence of flips that matches the beginning of either target sequence.\n", + "\n", + "States:\n", + "Start: The beginning, no flips yet.\n", + "H: The last flip was H.\n", + "HH: The last two flips were HH.\n", + "HT: The last two flips were HT.\n", + "\n", + "Absorbing states (end of the process):\n", + "HHH: Target sequence 1 reached.\n", + "HTH: Target sequence 2 reached.\n", + "\n", + "Let $p$ be the probability of flipping heads, $p = 0.5$, and $q$ be the probability of flipping tails, $q = 1 - p = 0.5$.\n", + "\n", + "Let $E_S$ be the probability that HHH occurs before HTH, starting from the Start state. This is what we want to find, $P(A) = E_S$.\n", + "Let $E_H$ be the probability that HHH occurs before HTH, given that the last flip was H.\n", + "Let $E_{HH}$ be the probability that HHH occurs before HTH, given that the last two flips were HH.\n", + "Let $E_{HT}$ be the probability that HHH occurs before HTH, given that the last two flips were HT.\n", + "\n", + "From the Start state:\n", + "If the first flip is H (prob $p$), we move to state H.\n", + "If the first flip is T (prob $q$), we remain at the Start state, as neither target sequence starts with T.\n", + "$E_S = p E_H + q E_S$\n", + "\n", + "From state H:\n", + "If the next flip is H (prob $p$), we move to state HH.\n", + "If the next flip is T (prob $q$), we move to state HT.\n", + "$E_H = p E_{HH} + q E_{HT}$\n", + "\n", + "From state HH:\n", + "If the next flip is H (prob $p$), we reach the HHH sequence, and the process stops with HHH occurring first. The probability of this event is 1.\n", + "If the next flip is T (prob $q$), we move to state HT.\n", + "$E_{HH} = p \\times 1 + q E_{HT} = p + q E_{HT}$\n", + "\n", + "From state HT:\n", + "If the next flip is H (prob $p$), we reach the HTH sequence, and the process stops with HTH occurring first. The probability of HHH occurring before HTH in this case is 0.\n", + "If the next flip is T (prob $q$), we return to the Start state, as the suffix no longer matches the beginning of either target sequence.\n", + "$E_{HT} = p \\times 0 + q E_S = q E_S$\n", + "\n", + "Now we have a system of linear equations:\n", + "1. $E_S = p E_H + q E_S$\n", + "2. $E_H = p E_{HH} + q E_{HT}$\n", + "3. $E_{HH} = p + q E_{HT}$\n", + "4. $E_{HT} = q E_S$\n", + "\n", + "Substitute equation 4 into equation 3:\n", + "$E_{HH} = p + q (q E_S) = p + q^2 E_S$\n", + "\n", + "Substitute the expression for $E_{HH}$ and equation 4 into equation 2:\n", + "$E_H = p (p + q^2 E_S) + q (q E_S) = p^2 + p q^2 E_S + q^2 E_S = p^2 + (p q^2 + q^2) E_S = p^2 + q^2 (p + 1) E_S$\n", + "\n", + "Substitute the expression for $E_H$ into equation 1:\n", + "$E_S = p (p^2 + q^2 (p + 1) E_S) + q E_S$\n", + "$E_S = p^3 + p q^2 (p + 1) E_S + q E_S$\n", + "$E_S - q E_S = p^3 + p q^2 (p + 1) E_S$\n", + "$E_S (1 - q) = p^3 + p q^2 (p + 1) E_S$\n", + "$E_S p = p^3 + p q^2 (p + 1) E_S$\n", + "\n", + "If $p \\neq 0$, we can divide by $p$:\n", + "$E_S = p^2 + q^2 (p + 1) E_S$\n", + "$E_S - q^2 (p + 1) E_S = p^2$\n", + "$E_S (1 - q^2 (p + 1)) = p^2$\n", + "\n", + "Substitute $p = 0.5$ and $q = 0.5$:\n", + "$p^2 = 0.25$\n", + "$q^2 = 0.25$\n", + "$p + 1 = 1.5$\n", + "$q^2 (p + 1) = 0.25 \\times 1.5 = 0.375$\n", + "$1 - q^2 (p + 1) = 1 - 0.375 = 0.625$\n", + "\n", + "$E_S (0.625) = 0.25$\n", + "$E_S = \\frac{0.25}{0.625} = \\frac{250}{625} = \\frac{1}{2.5} = \\frac{2}{5} = 0.4$\n", + "\n", + "So, the probability that HHH occurs before HTH is $P(A) = E_S = 0.4$.\n", + "The probability that HTH occurs before HHH is $P(B) = 1 - P(A) = 1 - 0.4 = 0.6$.\n", + "\n", + "Therefore, HTH is more likely to happen first.\n", + "\n", + "Alternative approach using expected number of flips.\n", + "\n", + "Consider the waiting times for each pattern.\n", + "Let $E_1$ be the expected number of flips until HHH appears. $E_1 = 1/p^3 = 1/(0.5)^3 = 1/0.125 = 8$.\n", + "Let $E_2$ be the expected number of flips until HTH appears.\n", + "\n", + "Consider the states and transitions for the occurrence of HTH.\n", + "Let $E_{HTH}$ be the expected number of flips to get HTH.\n", + "Starting from the beginning:\n", + "If we flip T (prob 0.5), we stay at the start.\n", + "If we flip H (prob 0.5), we are one step closer.\n", + "\n", + "Let $m = E_{HTH}$.\n", + "$m = 1 + 0.5 m + 0.5 E_H$\n", + "where $E_H$ is the expected number of additional flips needed to get HTH given the last flip was H.\n", + "\n", + "From state H:\n", + "If we flip H (prob 0.5), we go to HH.\n", + "If we flip T (prob 0.5), we go to HT.\n", + "\n", + "$E_H = 1 + 0.5 E_{HH} + 0.5 E_{HT}$\n", + "where $E_{HH}$ is the expected number of additional flips needed to get HTH given the last two flips were HH.\n", + "where $E_{HT}$ is the expected number of additional flips needed to get HTH given the last two flips were HT.\n", + "\n", + "From state HH:\n", + "If we flip H (prob 0.5), done.\n", + "If we flip T (prob 0.5), back to start.\n", + "$E_{HH} = 1 + 0.5 \\times 0 + 0.5 m = 1 + 0.5 m$\n", + "\n", + "From state HT:\n", + "If we flip H (prob 0.5), done.\n", + "If we flip T (prob 0.5), back to HT.\n", + "$E_{HT} = 1 + 0.5 \\times 0 + 0.5 E_{HT}$\n", + "$0.5 E_{HT} = 1 \\implies E_{HT} = 2$\n", + "\n", + "Substitute back:\n", + "$E_{HH} = 1 + 0.5 m$\n", + "$E_H = 1 + 0.5 (1 + 0.5 m) + 0.5 (2) = 1 + 0.5 + 0.25 m + 1 = 2.5 + 0.25 m$\n", + "$m = 1 + 0.5 m + 0.5 (2.5 + 0.25 m) = 1 + 0.5 m + 1.25 + 0.125 m$\n", + "$m = 2.25 + 0.625 m$\n", + "$m - 0.625 m = 2.25$\n", + "$0.375 m = 2.25$\n", + "$m = \\frac{2.25}{0.375} = \\frac{2250}{375} = 6$\n", + "\n", + "Expected number of flips for HTH is 10. (Error in calculation)\n", + "\n", + "Let's re-calculate expected number of flips using a different method.\n", + "\n", + "Let $E$ be the expected number of flips until the pattern occurs.\n", + "For HHH: $E = 1/p + 1/p^2 + 1/p^3 = 2 + 4 + 8 = 14$ (incorrect formula usage)\n", + "\n", + "Consider the expected waiting time for a pattern.\n", + "For a pattern $B$, let $E_B$ be the expected waiting time.\n", + "Let $S$ be the set of all finite sequences of coin flips.\n", + "Consider the events that the patterns end at time $n$.\n", + "\n", + "Gambler's Ruin Problem analogy.\n", + "\n", + "Consider the probability of HHH occurring before HTH.\n", + "Condition on the first few flips.\n", + "If the sequence starts with T, we are back to the start.\n", + "If the sequence starts with HT, then HTH will occur next.\n", + "If the sequence starts with HHT, then HHH might occur.\n", + "\n", + "Consider the first three flips:\n", + "HHH (prob 1/8) - HHH occurs\n", + "HHT (prob 1/8)\n", + "HTH (prob 1/8) - HTH occurs\n", + "HTT (prob 1/8)\n", + "THH (prob 1/8)\n", + "THT (prob 1/8)\n", + "TTH (prob 1/8)\n", + "TTT (prob 1/8)\n", + "\n", + "If the first three flips are HHH, HHH occurs first.\n", + "If the first three flips are HTH, HTH occurs first.\n", + "\n", + "Let $P$ be the probability that HHH occurs before HTH.\n", + "Condition on the first flip:\n", + "If T (prob 0.5), we start over, probability is still $P$.\n", + "If H (prob 0.5), we need to consider the next flips.\n", + "\n", + "If first flip is H:\n", + "Next flip is H (prob 0.5) -> HH\n", + "Next flip is T (prob 0.5) -> HT\n", + "\n", + "If we are at HH:\n", + "Next flip is H (prob 0.5) -> HHH (win for HHH)\n", + "Next flip is T (prob 0.5) -> HHT (restart, need to compare HHH and HTH from here)\n", + "\n", + "If we are at HT:\n", + "Next flip is H (prob 0.5) -> HTH (win for HTH)\n", + "Next flip is T (prob 0.5) -> HTT (restart)\n", + "\n", + "Let $P$ be the prob(HHH before HTH).\n", + "$P = 0.5 \\times P (\\text{HHH before HTH} | \\text{starts with T})$\n", + " $+ 0.5 \\times P (\\text{HHH before HTH} | \\text{starts with H})$\n", + "$P = 0.5 P + 0.5 P(\\text{HHH before HTH} | \\text{starts with H})$\n", + "\n", + "Let $P_H = P(\\text{HHH before HTH} | \\text{starts with H})$\n", + "Condition on the second flip:\n", + "$P_H = 0.5 P(\\text{HHH before HTH} | \\text{is HH})$\n", + " $+ 0.5 P(\\text{HHH before HTH} | \\text{is HT})$\n", + "\n", + "Let $P_{HH} = P(\\text{HHH before HTH} | \\text{is HH})$\n", + "Condition on the third flip:\n", + "$P_{HH} = 0.5 P(\\text{HHH before HTH} | \\text{is HHH}) + 0.5 P(\\text{HHH before HTH} | \\text{is HHT})$\n", + "$P_{HH} = 0.5 \\times 1 + 0.5 P_T$, where $P_T$ is the probability from start after HHT, which brings us back to comparing HHH and HTH from the start. So $P_T = P$.\n", + "$P_{HH} = 0.5 + 0.5 P$\n", + "\n", + "Let $P_{HT} = P(\\text{HHH before HTH} | \\text{is HT})$\n", + "Condition on the third flip:\n", + "$P_{HT} = 0.5 P(\\text{HHH before HTH} | \\text{is HTH}) + 0.5 P(\\text{HHH before HTH} | \\text{is HTT})$\n", + "$P_{HT} = 0.5 \\times 0 + 0.5 P = 0.5 P$\n", + "\n", + "Substitute back:\n", + "$P_H = 0.5 (0.5 + 0.5 P) + 0.5 (0.5 P) = 0.25 + 0.25 P + 0.25 P = 0.25 + 0.5 P$\n", + "\n", + "Substitute into the first equation:\n", + "$P = 0.5 P + 0.5 P_H = 0.5 P + 0.5 (0.25 + 0.5 P) = 0.5 P + 0.125 + 0.25 P$\n", + "$P = 0.75 P + 0.125$\n", + "$P - 0.75 P = 0.125$\n", + "$0.25 P = 0.125$\n", + "$P = \\frac{0.125}{0.25} = 0.5$\n", + "\n", + "Something is wrong.\n", + "\n", + "Let's use the recurrence relations approach again, carefully.\n", + "Let $E_S$ be the probability that HHH appears before HTH, starting from the empty sequence.\n", + "$E_S = p E_H + q E_T$, where $E_T = E_S$ by symmetry.\n", + "$E_S = 0.5 E_H + 0.5 E_S \\implies 0.5 E_S = 0.5 E_H \\implies E_S = E_H$. This is wrong.\n", + "\n", + "Let's use the notation from the first approach.\n", + "$P(\\text{HHH before HTH})$\n", + "\n", + "States: $\\emptyset, H, HH, HT$.\n", + "Let $P_{\\emptyset}$ be the probability starting from the beginning.\n", + "Let $P_H$ be the probability starting with H.\n", + "Let $P_{HH}$ be the probability starting with HH.\n", + "Let $P_{HT}$ be the probability starting with HT.\n", + "\n", + "$P_{\\emptyset} = 0.5 P_H + 0.5 P_{\\emptyset}$\n", + "$0.5 P_{\\emptyset} = 0.5 P_H \\implies P_{\\emptyset} = P_H$\n", + "\n", + "$P_H = 0.5 P_{HH} + 0.5 P_{HT}$\n", + "$P_{HH} = 0.5 \\times 1 + 0.5 P_{HT}$ (If next is H, HHH occurs, prob 1. If next is T, state HT)\n", + "$P_{HT} = 0.5 \\times 0 + 0.5 P_{\\emptyset}$ (If next is H, HTH occurs, prob 0. If next is T, back to start)\n", + "\n", + "Substitute $P_{HT}$:\n", + "$P_{HH} = 0.5 + 0.5 (0.5 P_{\\emptyset}) = 0.5 + 0.25 P_{\\emptyset}$\n", + "\n", + "Substitute into $P_H$:\n", + "$P_H = 0.5 (0.5 + 0.25 P_{\\emptyset}) + 0.5 (0.5 P_{\\emptyset})$\n", + "$P_H = 0.25 + 0.125 P_{\\emptyset} + 0.25 P_{\\emptyset} = 0.25 + 0.375 P_{\\emptyset}$\n", + "\n", + "Since $P_{\\emptyset} = P_H$:\n", + "$P_{\\emptyset} = 0.25 + 0.375 P_{\\emptyset}$\n", + "$P_{\\emptyset} - 0.375 P_{\\emptyset} = 0.25$\n", + "$0.625 P_{\\emptyset} = 0.25$\n", + "$P_{\\emptyset} = \\frac{0.25}{0.625} = 0.4$\n", + "\n", + "The probability that HHH occurs before HTH is 0.4.\n", + "The probability that HTH occurs before HHH is $1 - 0.4 = 0.6$.\n", + "\n", + "So HTH is more likely to happen first.\n", + "\n", + "Let's verify with a small number of flips.\n", + "Possible sequences of length 3: HHH, HHT, HTH, HTT, THH, THT, TTH, TTT (all prob 1/8).\n", + "HHH occurs first with HHH.\n", + "HTH occurs first with HTH.\n", + "If we get HHT, we continue.\n", + "If we get HTT, we continue.\n", + "If we get THH, we continue.\n", + "If we get THT, we continue.\n", + "If we get TTH, we continue.\n", + "If we get TTT, we continue.\n", + "\n", + "Consider the absorbing states.\n", + "Once we reach HHH or HTH, the process stops.\n", + "Consider paths to these states.\n", + "\n", + "Paths to HHH: HHH\n", + "Paths to HTH: HTH\n", + "\n", + "Consider sequences where the first occurrence of HHH or HTH happens at the end.\n", + "Length 3: HHH, HTH.\n", + "Length 4: THHH, CTHH (C != T), ...\n", + "Sequences ending in HHH but not containing HTH before:\n", + "THHH\n", + "Sequences ending in HTH but not containing HHH before:\n", + "THTH, HTTH (impossible), ...\n", + "\n", + "Consider the case where the process ends at the 3rd flip.\n", + "Prob(HHH) = 1/8\n", + "Prob(HTH) = 1/8\n", + "\n", + "Consider the case where the process ends at the 4th flip.\n", + "Ending with HHH: THHH (prob 1/16)\n", + "Ending with HTH: THTH (prob 1/16)\n", + "\n", + "Consider the structure of the sequences.\n", + "If HTH occurs, the preceding sequence cannot end in HH.\n", + "If HHH occurs, the preceding sequence cannot end in HT.\n", + "\n", + "Consider sequences starting with H.\n", + "HH -> HHH or HHT\n", + "HT -> HTH or HTT\n", + "\n", + "Consider runs of heads.\n", + "If we get T, we reset.\n", + "If we get H, then TH, HTH.\n", + "\n", + "Consider the first time we get HT. If the next is H, HTH occurs.\n", + "Consider the first time we get HH. If the next is H, HHH occurs.\n", + "\n", + "If the sequence starts with T, we are back to the start.\n", + "\n", + "Consider the event that HHH occurs before HTH.\n", + "This means the sequence ends with HHH, and HTH has not appeared before.\n", + "\n", + "Consider the event that HTH occurs before HHH.\n", + "This means the sequence ends with HTH, and HHH has not appeared before.\n", + "\n", + "Consider the difference between the two patterns.\n", + "HHH requires two consecutive heads before the final H.\n", + "HTH requires HT before the final H.\n", + "\n", + "If we are in state HH, the next flip determines if HHH occurs.\n", + "If we are in state HT, the next flip determines if HTH occurs.\n", + "\n", + "The problem is symmetric with respect to the outcome of flips.\n", + "The probabilities are fixed.\n", + "\n", + "Final check of the recurrence relations.\n", + "The states represent the longest suffix that is a prefix of either target sequence.\n", + "States: $\\emptyset, H, HH, HT$.\n", + "Transitions are correct.\n", + "The probabilities of moving between states are correct.\n", + "The conditions for termination are correct.\n", + "The system of equations seems correctly set up and solved.\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "### Answer" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "Solution:\n", + "Let $A$ be the event that the sequence HHH occurs before the sequence HTH.\n", + "Let $B$ be the event that the sequence HTH occurs before the sequence HHH.\n", + "We want to find the probabilities of these events.\n", + "\n", + "We can use the method of conditioning on the current state of the sequence relative to the target patterns. The states are defined by the longest suffix of the current sequence that is a prefix of either HHH or HTH. The states are:\n", + "- $\\emptyset$: The starting state, no flips yet.\n", + "- H: The last flip was H.\n", + "- HH: The last two flips were HH.\n", + "- HT: The last two flips were HT.\n", + "\n", + "Let $P_S$ be the probability that HHH occurs before HTH starting from state $S$. We want to find $P_{\\emptyset}$.\n", + "\n", + "From state $\\emptyset$: $P_{\\emptyset} = 0.5 P_H + 0.5 P_{\\emptyset}$\n", + "From state H: $P_H = 0.5 P_{HH} + 0.5 P_{HT}$\n", + "From state HH: $P_{HH} = 0.5 \\times 1 + 0.5 P_{HT}$ (If next is H, HHH occurs; if next is T, go to HT)\n", + "From state HT: $P_{HT} = 0.5 \\times 0 + 0.5 P_{\\emptyset}$ (If next is H, HTH occurs; if next is T, go to $\\emptyset$)\n", + "\n", + "Substituting the expressions:\n", + "$P_{HT} = 0.5 P_{\\emptyset}$\n", + "$P_{HH} = 0.5 + 0.5 (0.5 P_{\\emptyset}) = 0.5 + 0.25 P_{\\emptyset}$\n", + "$P_H = 0.5 (0.5 + 0.25 P_{\\emptyset}) + 0.5 (0.5 P_{\\emptyset}) = 0.25 + 0.125 P_{\\emptyset} + 0.25 P_{\\emptyset} = 0.25 + 0.375 P_{\\emptyset}$\n", + "$P_{\\emptyset} = 0.5 (0.25 + 0.375 P_{\\emptyset}) + 0.5 P_{\\emptyset} = 0.125 + 0.1875 P_{\\emptyset} + 0.5 P_{\\emptyset}$\n", + "$P_{\\emptyset} = 0.125 + 0.6875 P_{\\emptyset}$\n", + "$P_{\\emptyset} (1 - 0.6875) = 0.125$\n", + "$0.3125 P_{\\emptyset} = 0.125$\n", + "$P_{\\emptyset} = \\frac{0.125}{0.3125} = \\frac{1250}{3125} = \\frac{2}{5} = 0.4$\n", + "\n", + "The probability that HHH occurs before HTH is $0.4$.\n", + "The probability that HTH occurs before HHH is $1 - 0.4 = 0.6$.\n", + "\n", + "Final Answer: The final answer is $\\boxed{HTH}$" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } ], - "text/plain": [ - "" + "source": [ + "response = client.models.generate_content(\n", + " model=MODEL_ID,\n", + " contents=\"You repeatedly flipped a coin until you either flip three heads, or heads tails heads. Which is more likely to happen first?\",\n", + ")\n", + "\n", + "display(Markdown(\"### Thoughts\"))\n", + "display(Markdown(response.candidates[0].content.parts[0].text))\n", + "display(Markdown(\"### Answer\"))\n", + "display(Markdown(response.candidates[0].content.parts[1].text))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "m9RG4DRCm1vY" + }, + "source": [ + "### **Example 6**: Mathematical brain teaser" ] - }, - "metadata": {}, - "output_type": "display_data" }, { - "data": { - "text/markdown": [ - "Here's the solution:\n", - "\n", - "**50 * (8 + 7) - 4 = 746**\n", - "\n", - "**Explanation:**\n", - "\n", - "1. **8 + 7 = 15**\n", - "2. **50 * 15 = 750**\n", - "3. **750 - 4 = 746**\n" + "cell_type": "code", + "execution_count": 19, + "metadata": { + "id": "A0_4uP5Wm6yx" + }, + "outputs": [ + { + "data": { + "text/markdown": [ + "### Thoughts" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "Here's a thought process to arrive at the solution:\n", + "\n", + "1. **Analyze the Goal and Numbers:** The target is 746. The available numbers are 8, 7, 50, and 4. Notice the target is a fairly large number, hinting that multiplication will likely be involved.\n", + "\n", + "2. **Consider the Magnitudes:** 50 is the largest number. Multiplying it by another number might get us closer to the target faster.\n", + "\n", + "3. **Initial Multiplication Ideas with 50:**\n", + " * 50 * 8 = 400 (Too small)\n", + " * 50 * 7 = 350 (Too small)\n", + " * 50 * 4 = 200 (Too small)\n", + "\n", + "4. **Combining Multiplication:** Maybe multiplying two of the smaller numbers first, then multiplying by 50 could work.\n", + " * 8 * 7 = 56. Then 56 * 50 is much larger than 746.\n", + " * 8 * 4 = 32. Then 32 * 50 is larger than 746.\n", + " * 7 * 4 = 28. Then 28 * 50 is larger than 746.\n", + "\n", + "5. **Re-evaluate the Role of 50:** Since multiplying 50 by another individual number isn't enough and multiplying it by products of the other numbers is too large, perhaps 50 should be added or subtracted later.\n", + "\n", + "6. **Focus on Getting Closer to 746 without 50 (initially):** Try combinations of 8, 7, and 4 to get a number that, when combined with 50, gets closer to 746.\n", + " * 8 * 7 = 56. What needs to be done to 56 to get near 700? Multiplying by a large number.\n", + " * 8 * 4 = 32\n", + " * 7 * 4 = 28\n", + "\n", + "7. **Consider Combining Operations:** Let's go back to multiplying 50, but consider adding or subtracting the other numbers.\n", + "\n", + "8. **Trial and Error with 50 as a Multiplier:**\n", + " * 50 * (something involving 8, 7, 4). We need the \"something\" to be roughly around 14 or 15 (746 / 50 ≈ 14.92).\n", + "\n", + "9. **Trying to get 14 or 15 with 8, 7, 4:**\n", + " * 8 + 7 - 4 = 11 (Too small)\n", + " * 8 - 7 + 4 = 5 (Too small)\n", + " * 8 * (7 - 4) = 8 * 3 = 24 (Too large)\n", + " * (8 - 7) * 4 = 1 * 4 = 4 (Too small)\n", + "\n", + "10. **Think About Getting Close to 700 with the other numbers:**\n", + " * 8 * 7 * something... no, we can only use numbers once.\n", + "\n", + "11. **Consider Using 50 as a Subtrahend:** If we get a number *larger* than 746, we could subtract 50.\n", + "\n", + "12. **Back to Multiplication with the other numbers:**\n", + " * 8 * 7 = 56. What do we need to add/multiply to get closer to 746?\n", + " * Try multiplying 50 by one of the other numbers and then adjusting.\n", + "\n", + "13. **Focus on getting a number slightly above 746:**\n", + " * 50 * something + something else.\n", + " * 50 * 8 = 400. Need to add around 346.\n", + " * 50 * 7 = 350. Need to add around 396.\n", + "\n", + "14. **Consider Multiplying Two Numbers First:**\n", + " * 50 * 8 = 400. Can we get 346 with 7 and 4? 7 * 4 = 28 (not close).\n", + " * 50 * 7 = 350. Can we get 396 with 8 and 4? 8 * 4 = 32 (not close).\n", + "\n", + "15. **Think about multiplying two numbers to get close to a factor of 746:** Not easily apparent.\n", + "\n", + "16. **Try a different arrangement of multiplication:**\n", + " * 50 * (8 + something). We need \"something\" to be small.\n", + " * 50 * (7 + something).\n", + " * 50 * (4 + something).\n", + "\n", + "17. **Consider a combination where multiplication creates a larger number, and subtraction brings it down:**\n", + " * 50 * 8 = 400. If we multiply 7 and 4 we get 28. 400 + 28 is too small.\n", + " * What if we multiply 50 by the *sum* of some numbers?\n", + "\n", + "18. **Focus on getting something close to 700:**\n", + " * 50 * (8 + 7) = 50 * 15 = 750. We're very close! Now subtract 4: 750 - 4 = 746. **Solution found!**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "### Answer" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "Here's the solution:\n", + "\n", + "**50 * (8 + 7) - 4 = 746**\n", + "\n", + "**Explanation:**\n", + "\n", + "1. **8 + 7 = 15**\n", + "2. **50 * 15 = 750**\n", + "3. **750 - 4 = 746**\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } ], - "text/plain": [ - "" + "source": [ + "my_prompt = \"\"\"Add mathematical operations (additions, substractions, multiplications) to get 746 using these numbers only once: \n", + "8, 7, 50, and 4\n", + "\"\"\"\n", + "\n", + "\n", + "response = client.models.generate_content(\n", + " model=MODEL_ID,\n", + " contents=my_prompt,\n", + ")\n", + "\n", + "display(Markdown(\"### Thoughts\"))\n", + "display(Markdown(response.candidates[0].content.parts[0].text))\n", + "display(Markdown(\"### Answer\"))\n", + "display(Markdown(response.candidates[0].content.parts[1].text))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "lND4jB6MrsSk" + }, + "source": [ + "## Next Steps\n", + "\n", + "- Explore the Vertex AI [Cookbook](https://cloud.google.com/vertex-ai/generative-ai/docs/cookbook) for a curated, searchable gallery of notebooks for Generative AI.\n", + "- Explore other notebooks and samples in the [Google Cloud Generative AI repository](https://github.com/GoogleCloudPlatform/generative-ai)." ] - }, - "metadata": {}, - "output_type": "display_data" } - ], - "source": [ - "my_prompt = \"\"\"Add mathematical operations (additions, substractions, multiplications) to get 746 using these numbers only once: \n", - "8, 7, 50, and 4\n", - "\"\"\"\n", - "\n", - "\n", - "response = client.models.generate_content(\n", - " model=MODEL_ID,\n", - " contents=my_prompt,\n", - ")\n", - "\n", - "display(Markdown(\"### Thoughts\"))\n", - "display(Markdown(response.candidates[0].content.parts[0].text))\n", - "display(Markdown(\"### Answer\"))\n", - "display(Markdown(response.candidates[0].content.parts[1].text))" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "lND4jB6MrsSk" - }, - "source": [ - "## Next Steps\n", - "\n", - "- Explore the Vertex AI [Cookbook](https://cloud.google.com/vertex-ai/generative-ai/docs/cookbook) for a curated, searchable gallery of notebooks for Generative AI.\n", - "- Explore other notebooks and samples in the [Google Cloud Generative AI repository](https://github.com/GoogleCloudPlatform/generative-ai)." - ] - } - ], - "metadata": { - "colab": { - "name": "intro_gemini_2_0_flash_thinking_mode.ipynb", - "toc_visible": true - }, - "environment": { - "kernel": "conda-base-py", - "name": "workbench-notebooks.m124", - "type": "gcloud", - "uri": "us-docker.pkg.dev/deeplearning-platform-release/gcr.io/workbench-notebooks:m124" - }, - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "conda-base-py" + ], + "metadata": { + "colab": { + "name": "intro_gemini_2_0_flash_thinking_mode.ipynb", + "toc_visible": true + }, + "kernelspec": { + "display_name": "Python 3", + "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.10.14" - } - }, - "nbformat": 4, - "nbformat_minor": 4 + "nbformat": 4, + "nbformat_minor": 0 }