{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "f5162a52",
   "metadata": {},
   "source": [
    "# String Creation and Accessing\n",
    "\n",
    "Strings are created through assignment operator using **single**, **double**, or **triple** quotes: 'hello', \"hello\", \"\"\"hello\"\"\".\n",
    "\n",
    "The built-in Python function `len()` works with string as well."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e9f5d02c",
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys\n",
    "from pathlib import Path\n",
    "\n",
    "# Find project root by looking for _config.yml\n",
    "current = Path.cwd()\n",
    "for parent in [current, *current.parents]:\n",
    "    if (parent / '_config.yml').exists():\n",
    "        project_root = parent\n",
    "        break\n",
    "else:\n",
    "    project_root = Path.cwd().parent.parent\n",
    "\n",
    "# Add project root to path\n",
    "sys.path.insert(0, str(project_root))\n",
    "\n",
    "# Import shared teaching helpers and cell magics\n",
    "from shared import thinkpython, diagram, jupyturtle, structshape\n",
    "from shared.download import download\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "711a942f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'str'>\n",
      "34\n"
     ]
    }
   ],
   "source": [
    "s = 'supercalifragilisticexpialidocious'\n",
    "\n",
    "print(type(s))\n",
    "\n",
    "n = len(s)\n",
    "print(n)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e59d375d",
   "metadata": {},
   "source": [
    "Single and double quotes are interchangeable for single-line strings. Triple quotes are used for multi-line strings or strings that contain both single and double quotes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "128fc518",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello, world!\n",
      "Hello, world!\n",
      "This is\n",
      "a multi-line\n",
      "string.\n"
     ]
    }
   ],
   "source": [
    "s1 = 'Hello, world!'\n",
    "s2 = \"Hello, world!\"\n",
    "s3 = \"\"\"This is\n",
    "a multi-line\n",
    "string.\"\"\"\n",
    "\n",
    "print(s1)\n",
    "print(s2)\n",
    "print(s3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7d176b3e",
   "metadata": {},
   "source": [
    "## Escape Sequences and Raw Strings\n",
    "\n",
    "Inside a string, a backslash `\\` introduces an **escape sequence** — a two-character combination that represents a special character:\n",
    "\n",
    "| Escape Sequence | Meaning | Example output |\n",
    "|---|---|---|\n",
    "| `\\n` | Newline | moves to the next line |\n",
    "| `\\t` | Tab | inserts a horizontal tab |\n",
    "| `\\\\` | Backslash | a literal `\\` |\n",
    "| `\\\"` | Double quote | `\"` inside a double-quoted string |\n",
    "| `\\'` | Single quote | `'` inside a single-quoted string |\n",
    "\n",
    "A **raw string** is prefixed with `r` (or `R`) and treats backslashes as literal characters — no escape sequences are processed. Raw strings are especially useful for regular expression patterns and file paths."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "5e03e05a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "line1\n",
      "line2\n",
      "col1\tcol2\n",
      "C:\\Users\\ty\n",
      "C:\\Users\\ty\n"
     ]
    }
   ],
   "source": [
    "print(\"line1\\nline2\")       # newline\n",
    "print(\"col1\\tcol2\")         # tab\n",
    "print(\"C:\\\\Users\\\\ty\")      # literal backslashes\n",
    "print(r\"C:\\Users\\ty\")       # raw string — same result, easier to read\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "0e92a884",
   "metadata": {
    "tags": [
     "thebe-interactive"
    ]
   },
   "outputs": [],
   "source": [
    "### EXERCISE: Escape Sequences and Raw Strings\n",
    "# Difficulty: Basic\n",
    "# 1. Print two words on two lines using \\n\n",
    "# 2. Print two values separated by a tab using \\t\n",
    "# 3. Print a Windows path using a raw string\n",
    "### Your code starts here:\n",
    "\n",
    "\n",
    "### Your code ends here."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "6431ebc9",
   "metadata": {
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "apple\n",
      "banana\n",
      "score\t95\n",
      "C:\\Users\\alice\\data\n"
     ]
    }
   ],
   "source": [
    "# Solution\n",
    "print(\"apple\\nbanana\")\n",
    "print(\"score\\t95\")\n",
    "print(r\"C:\\Users\\alice\\data\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "83eebc6e",
   "metadata": {},
   "source": [
    "## Indexing and Slicing\n",
    "\n",
    "Strings are **sequences**, meaning each character has a numbered position called an **index**. Python uses zero-based indexing: the first character is at index `0`, the second at index `1`, and so on. Negative indices count from the end of the string."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "19267d6c",
   "metadata": {},
   "source": [
    "### String Indexing\n",
    "\n",
    "As a sequence type, the expression in brackets is an **index**, so called because it *indicates* which character in the sequence to select. String indexing is `0`-based."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "0a1e4a1c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "b\n"
     ]
    }
   ],
   "source": [
    "fruit = \"banana\"\n",
    "print(fruit[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b0016829",
   "metadata": {},
   "source": [
    "You can select a character from a string with the **bracket operator**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "133edb06",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "P\n",
      "y\n",
      "n\n",
      "o\n"
     ]
    }
   ],
   "source": [
    "s = 'Python'\n",
    "\n",
    "print(s[0])    # 'P'  — first character\n",
    "print(s[1])    # 'y'  — second character\n",
    "print(s[-1])   # 'n'  — last character\n",
    "print(s[-2])   # 'o'  — second to last"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ddc6f0c4",
   "metadata": {},
   "source": [
    "As a reminder, the last letter of a string is the length of the string minus 1. If you use `len()` to access the last element of the sequence you get an `IndexError` (**`string index out of range`**) because there is no element there to be accessed: **0-based indexing**. \n",
    "\n",
    "Also because of 0-based indexing, to get the last character, you have to subtract `1` from `n` (**n-1**)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "9df74cbe",
   "metadata": {},
   "outputs": [],
   "source": [
    "fruit = 'banana'\n",
    "n = len(fruit)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "53ddfe0f",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%expect IndexError\n",
    "fruit[n]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "2ac4ca15",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'a'"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fruit[n-1]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "83c2f759",
   "metadata": {},
   "source": [
    "Often forgotten, there's an easier way to access the last element of a sequence: negative indexing, which counts backward from the end. The index `-1` selects the last letter, `-2` selects the second to last, and so on."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "2858ddb1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'a'"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fruit[-1]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eab58074",
   "metadata": {},
   "source": [
    "The index in brackets can be a variable.\n",
    "Or an expression that contains variables and operators."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "8e8d6a17",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a\n",
      "n\n",
      "b a n a n a "
     ]
    }
   ],
   "source": [
    "i = 1\n",
    "print(fruit[i])\n",
    "print(fruit[i+1])\n",
    "\n",
    "for i in range(len(fruit)):\n",
    "    print(fruit[i], end=' ')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f805abb1",
   "metadata": {},
   "source": [
    "Just like lists and tuples, the value of the **index** has to be an **integer** -- otherwise you get a `TypeError`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3c4fe527",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%expect TypeError\n",
    "fruit[1.5]\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8ee14893",
   "metadata": {},
   "source": [
    "It is tempting to use the `[]` operator on the left side of an\n",
    "assignment, with the intention of changing a character in a string. \n",
    "\n",
    "The result is a `TypeError`. In the error message, the object is the string and the \"item\" is the character we tried to assign. \n",
    "\n",
    "The reason for this error is that strings are **immutable**, which means you can't change an existing string. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "3d5bd98a",
   "metadata": {},
   "outputs": [],
   "source": [
    "greeting = 'hello, world'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "85172f02",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%expect TypeError\n",
    "greeting[0] = 'J'\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bb53ed01",
   "metadata": {},
   "source": [
    "The best you can do is create a new string that is a variation of the original."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "ad1d7467",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Jello, world'"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "new_greeting = 'J' + greeting[1:]     ### \"+\" is concatenate here\n",
    "new_greeting"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c3185ecf",
   "metadata": {},
   "source": [
    "This example concatenates a new first letter onto a slice of `greeting`.\n",
    "It has no effect on the original string."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "14e46b03",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'hello, world'"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "greeting"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "130aa560",
   "metadata": {},
   "source": [
    "### Slicing Strings\n",
    "\n",
    "Just like lists and tuples, a segment of a string is called a **slice**. Selecting a slice is similar to selecting a character. The general syntax of slicing is the same as lists and tuple:\n",
    "\n",
    "```python \n",
    "sequence[start:stop:step]\n",
    "``` \n",
    "Also, the parameters are start-inclusive and stop-exclusive.\n",
    "\n",
    "- `start` — index to begin at (inclusive, default `0`)\n",
    "- `stop` — index to end at (exclusive, default end of string)\n",
    "- `step` — how many characters to skip (default `1`)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "b1b70ae4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'ban'"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fruit = 'banana'\n",
    "fruit[0:3]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7825a1c3",
   "metadata": {},
   "source": [
    "The operator `[m:n]` returns the part of the string from the `m`th character to the `n`th character, including the first but **excluding** the second. This behavior is counterintuitive, but it might help to imagine the indices pointing *between* the characters, as in this figure:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "7df47fa3",
   "metadata": {
    "tags": [
     "remove-input"
    ]
   },
   "outputs": [],
   "source": [
    "from shared.diagram import make_binding, Element, Value\n",
    "\n",
    "binding = make_binding(\"fruit\", ' b a n a n a ')\n",
    "elements = [Element(Value(i), None) for i in range(7)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "3a07c99e",
   "metadata": {
    "tags": [
     "remove-input"
    ]
   },
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 135x54 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "from shared.diagram import diagram, adjust\n",
    "from matplotlib.transforms import Bbox\n",
    "\n",
    "width, height, x, y = [1.35, 0.54, 0.23, 0.39]\n",
    "\n",
    "ax = diagram(width, height)\n",
    "bbox = binding.draw(ax, x, y)\n",
    "bboxes = [bbox]\n",
    "\n",
    "def draw_elts(x, y, elements):\n",
    "    for elt in elements:\n",
    "        bbox = elt.draw(ax, x, y, draw_value=False)\n",
    "        bboxes.append(bbox)\n",
    "\n",
    "        x1 = (bbox.xmin + bbox.xmax) / 2\n",
    "        y1 = bbox.ymax + 0.02\n",
    "        y2 = y1 + 0.14\n",
    "        handle = plt.plot([x1, x1], [y1, y2], ':', lw=0.5, color='gray')\n",
    "        x += 0.105\n",
    "    \n",
    "draw_elts(x + 0.48, y - 0.25, elements)\n",
    "bbox = Bbox.union(bboxes)\n",
    "# adjust(x, y, bbox)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ec248f7b",
   "metadata": {},
   "source": [
    "For example, the slice `[3:6]` selects the letters `ana`, which means that `6` is **legal** as part of a **slice**, but **not** **legal** as an **index**.\n",
    "\n",
    "Also, \n",
    "- if you omit the first index, the slice starts at the beginning of the string.\n",
    "- if you omit the second index, the slice goes to the end of the string:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "42887b0a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello\n",
      "world!\n",
      "Hello\n",
      "Hlo ol!\n",
      "!dlrow ,olleH\n"
     ]
    }
   ],
   "source": [
    "s = 'Hello, world!'\n",
    "\n",
    "print(s[0:5])    # 'Hello'   — characters 0 through 4\n",
    "print(s[7:])     # 'world!'  — from index 7 to end\n",
    "print(s[:5])     # 'Hello'   — from start to index 4\n",
    "print(s[::2])    # every other character\n",
    "print(s[::-1])   ### 'reversed string' ###"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "63920578",
   "metadata": {},
   "source": [
    "If the first index is greater than or equal to the second, the result is an **empty string**, represented by two quotation marks. An empty string contains no characters and has length 0."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "f6a0be45",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "len(fruit[3:3]): 0\n",
      "Type of fruit[3:3]: <class 'str'>\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "''"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print(f\"len(fruit[3:3]): {len(fruit[3:3])}\")\n",
    "print(f\"Type of fruit[3:3]: {type(fruit[3:3])}\")\n",
    "fruit[3:3]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "030ac726",
   "metadata": {},
   "source": [
    "Continuing this example, what do you think `fruit[:]` means? Try it and\n",
    "see."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "2f33ded6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'banana'"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fruit[:]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9cfa64b8",
   "metadata": {},
   "source": [
    "To practice your slicing skills, play these in your head with string \"banana\", which may not be as easy as you think."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "9f8b44f2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'bnn'"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fruit[0:-1]                     \n",
    "fruit[-2:]                      \n",
    "fruit[0:-1:2]                   \n",
    "\n",
    "# print(fruit[0:-1])              ### all but the last letter: banan\n",
    "# print(fruit[-2:])               ### the last two letters: na\n",
    "# print(fruit[0:-1:2])            ### step is 2, so you get bnn"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "10ba446a",
   "metadata": {
    "tags": [
     "thebe-interactive"
    ]
   },
   "outputs": [],
   "source": [
    "### EXERCISE: Indexing and Slicing\n",
    "# Difficulty: Basic\n",
    "text = 'superpython'\n",
    "# 1. Print the first character\n",
    "# 2. Print the last character using negative indexing\n",
    "# 3. Print every second character\n",
    "# 4. Print the reversed string\n",
    "### Your code starts here:\n",
    "\n",
    "\n",
    "### Your code ends here."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "3670ac95",
   "metadata": {
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "s\n",
      "n\n",
      "spryhn\n",
      "nohtyprepus\n"
     ]
    }
   ],
   "source": [
    "# Solution\n",
    "text = 'superpython'\n",
    "print(text[0])\n",
    "print(text[-1])\n",
    "print(text[::2])\n",
    "print(text[::-1])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "33668dc2",
   "metadata": {},
   "source": [
    "## Concatenation and Repetition\n",
    "\n",
    "The `+` operator joins two strings together (**concatenation**). The `*` operator repeats a string a given number of times (**repetition**)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "07e14e8a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello, World!\n",
      "* * * * * * * * * * \n",
      "hahaha\n"
     ]
    }
   ],
   "source": [
    "first = 'Hello'\n",
    "last  = 'World'\n",
    "\n",
    "# Concatenation\n",
    "greeting = first + ', ' + last + '!'\n",
    "print(greeting)        # 'Hello, World!'\n",
    "\n",
    "# Repetition\n",
    "line = '* ' * 10\n",
    "print(line)            # '* * * * * * * * * * '\n",
    "\n",
    "print('ha' * 3)        # 'hahaha'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "eede96da",
   "metadata": {
    "tags": [
     "thebe-interactive"
    ]
   },
   "outputs": [],
   "source": [
    "### EXERCISE: Concatenation and Repetition\n",
    "# Difficulty: Basic\n",
    "first = 'Alice'\n",
    "last = 'Bob'\n",
    "# 1. Build and print: \"Alice & Bob\" using concatenation\n",
    "# 2. Print \"ha\" repeated 4 times\n",
    "# 3. Create a divider of 20 dashes and print it\n",
    "### Your code starts here:\n",
    "\n",
    "\n",
    "### Your code ends here."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "a1bd97c1",
   "metadata": {
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Alice & Bob\n",
      "hahahaha\n",
      "--------------------\n"
     ]
    }
   ],
   "source": [
    "# Solution\n",
    "first = 'Alice'\n",
    "last = 'Bob'\n",
    "print(first + \" & \" + last)\n",
    "print(\"ha\" * 4)\n",
    "print(\"-\" * 20)"
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Tags",
  "kernelspec": {
   "display_name": ".venv (3.13.7)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
