{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Строки"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Строка  &ndash; набор символов в кавычках. Одинарных, двойных или тройных. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Привет!\n",
      "John's dog\n",
      "\n",
      "Еду. Тихо. Слышны звоны\n",
      "Под копытом на снегу,\n",
      "Только серые вороны\n",
      "Расшумелись на лугу.\n",
      "\n"
     ]
    }
   ],
   "source": [
    "s1 = 'Привет!'\n",
    "s2 = \"John's dog\"\n",
    "s3 = '''\n",
    "Еду. Тихо. Слышны звоны\n",
    "Под копытом на снегу,\n",
    "Только серые вороны\n",
    "Расшумелись на лугу.\n",
    "'''\n",
    "print(s1)\n",
    "print(s2)\n",
    "print(s3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Индексация (нумерация символов) в строке начинается **с нуля**.  \n",
    "Обратная нумерация: последний элемент имеет индекс -1, предпоследний -2 и т.д. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "||||||Нумерация символов в строке |\n",
    "|:--|:--|:--|:--|:--|:--|\n",
    "| 0 | 1 | 2 | 3 | 4 | 5 | \n",
    "|<font size=+2>С|<font size=+2>Т|<font size=+2>Р|<font size=+2>О|<font size=+2>К|<font size=+2>А| \n",
    "| -6 | -5 | -4 | -3 | -2 | -1 | "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "К\n",
      "Р\n"
     ]
    }
   ],
   "source": [
    "s = 'СТРОКА'\n",
    "print(s[4])\n",
    "print(s[-4])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Про неизменяемость**.\n",
    "\n",
    "The _value_ of some objects can change. Objects whose value can change are said to be <em>mutable</em>; objects whose value is unchangeable once they are created are called immutable... An object’s mutability is determined by its type; for instance, numbers, **strings** and tuples are immutable, while dictionaries and lists are mutable.\n",
    "\n",
    "<div align=right>\n",
    "    <a href=https://docs.python.org/3/reference/datamodel.html#objects-values-and-types>The Python Language Reference. 3. Data model </a>\n",
    "</div>\n",
    "\n",
    "\n",
    "Доступ к символу `s[i]` &ndash; только на чтение, изменить отдельный символ строки нельзя. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Иллюстрации**:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "b\n"
     ]
    },
    {
     "ename": "TypeError",
     "evalue": "'str' object does not support item assignment",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-3-9ee0ece5952e>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[0ms\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;34m'banana'\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      2\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ms\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m \u001b[0ms\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;34m'c'\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m: 'str' object does not support item assignment"
     ]
    }
   ],
   "source": [
    "s = 'banana'\n",
    "print(s[0])\n",
    "s[0] = 'c'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "b: id = 39118000\n",
      "a: id = 39174960\n",
      "n: id = 6179760\n",
      "a: id = 39174960\n",
      "n: id = 6179760\n",
      "a: id = 39174960\n"
     ]
    }
   ],
   "source": [
    "for i in range(0,6):\n",
    "    print (f'{s[i]}: id = {id(s[i])}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "83475632"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "id(s)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "banana ananas\n"
     ]
    }
   ],
   "source": [
    "s += ' ananas'\n",
    "print(s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "84827440"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "id(s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "banana 84851568\n",
      "banana ananas 84852656\n"
     ]
    }
   ],
   "source": [
    "s = 'banana'\n",
    "print(s, id(s))\n",
    "s += ' ananas'\n",
    "print(s, id(s))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Escape-последовательности\n",
    "\n",
    "Escape-последовательность, или экранированная последовательность, или управляющая последовательность &ndash; это часть строки, которая начинается с символа \"\\\\\", за которым следует один или более символов. Такие конструкции не являются видимой частью строки, в том смысле, что при выводе их на экран функцией `print` выполняется некоторое действие или изображается нечто другое.\n",
    "\n",
    "В таблице приведены некоторые последовательности, работающие в Python 3 Shell и/или в среде Jupyter Notebook\n",
    "\n",
    "|Последовательность| Описание | Пример | Результат выполнения |\n",
    "|:---|:---|:---|:---|\n",
    "|`\\n`| Перенос строки (новая строка). | `print('привет\\nмир')` |<div style=\"font-family: monospace \">привет<br>мир</div> | \n",
    "|`\\t`| Горизонтальная табуляция. | `print('привет\\tмир')` |<div style=\"font-family: monospace \">привет&nbsp;&nbsp;&nbsp;&nbsp;мир</div> |\n",
    "|`\\r`|Возврат курсора в начало строки<sup>1</sup>. <br> Новые символы выводятся, \"заменяя\" старые. | `print('привет\\rмир')` |<div style=\"font-family: monospace \">мирвет</div> |\n",
    "|`\\b`|Аналог клавиши Backspace. Возврат курсора на одну позицию влево, удаление символа слева<sup>1</sup>.  | `print('привет\\bмир')` |<div style=\"font-family: monospace \">привемир</div> |\n",
    "|`\\N{описание символа}`|Выводит символ по его описанию в базе данных Юникода. Например, так можно вывести многие эмодзи<sup>2</sup>.| `print('\\N{flushed face}')` |😳| \n",
    "|`\\xhh`|Символ с шестнадцатеричным кодом hh (две шестнадцатеричные цифры).| `print('\\xC4')` |<div style=\"font-family: monospace \">Ä</div> |\n",
    "|`\\uhhhh`|16-битный символ Юникода, т.е. символ кодируемый двумя байтами (четыре шестнадцатеричные цифры).|`print('\\u265E')`|♞|\n",
    "|`\\Uhhhhhhhh`|32-битный символ Юникода, т.е. символ кодируемый четырьмя байтами (восемь шестнадцатеричных цифр). Таким способом тоже можно выводить эмодзи<sup>2</sup> | `print('\\U0001F609')` |😉|\n",
    "|`\\\\`|Экранирование обратного слэша. Позволяет включить в строку символ ```\\```. | `print('привет\\\\мир')` |<div style=\"font-family: monospace \">привет\\мир</div> |\n",
    "|`\\'`|Экранирование апострофа. Позволяет включить в строку символ апострофа ```'```. | `print('привет\\'мир')` |<div style=\"font-family: monospace \">привет'мир</div> |\n",
    "|`\\\"`|Экранирование кавычки. Позволяет включить в строку символ кавычки ```\"```. | `print(\"привет\\\"мир\")` |<div style=\"font-family: monospace \">привет\"мир</div> |\n",
    "|`\\[конец строки]`|Запись одной строки на нескольких строках в тексте программы. | `print('привет\\`<br>`всем\\`<br>`всем')` |<div style=\"font-family: monospace \">приветвсемвсем</div> |\n",
    "\n",
    "\n",
    "<sup>1</sup> Не работает в Shell (Windows)<br>\n",
    "<sup>2</sup> <a href=\"https://unicode.org/emoji/charts/emoji-list.html\">Emoji List, v13.1</a> \n",
    "\n",
    "Подробная информация: https://pyprog.pro/python/py/str/esqape_sec.html"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "\n",
    "**r-строки**, или _сырые_ строки. В строках вида `r'привет\\nмир'` игнорируются управляющие последовательности "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "**f-строки**. Возможность использования значений переменных внутри строки. Примеры, в том числе использования форматирования &ndash; ниже."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "31.41592\n",
      "31.42\n",
      "31.41592000\n",
      "3.141592e+01\n",
      "            31.41592\n",
      "31.41592            \n",
      "            31.41592\n"
     ]
    }
   ],
   "source": [
    "x = 31.41592      # число\n",
    "y = '31.41592'    # строка\n",
    "print(f'{x}')     # вывод \"как есть\"\n",
    "print(f'{x:.2f}') # два знака после десятичной точки\n",
    "print(f'{x:.8f}') # восемь знаков после десятичной точки\n",
    "print(f'{x:e}')   # вывод в экспоненциальном формате\n",
    "print(f'{x:20}')  # числа выравниваются по правому краю\n",
    "print(f'{y:20}')  # остальные строки - по левому краю\n",
    "print(f'{y:>20}') # но если очень хочется...\n",
    "                  # есть еще варианты < и  ^\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Краткий справочник по некоторым функциям и методам строк**<sup>3</sup>\n",
    "\n",
    "| Операция, функция или метод| Назначение  |\n",
    "|:---|:---|\n",
    "|`s1 + s2`|Конкатенация или слияние строк|\n",
    "|`s * n`|Повторение строки `n` раз|\n",
    "|`s[i]`|Доступ к символу по его индексу (отсчет индексов идёт с нуля)|\n",
    "|`s[i:j:step]`|Получение среза|\n",
    "|`len(s)`|Длина строки|\n",
    "|`s.find(str, start, end)`|Поиск подстроки в строке. Возвращает номер ***первого*** вхождения или -1, если подстрока не найдена. По умолчанию `start=0`, то есть поиск идет с начала строки, а `end` соответствует последнему символу строки.|\n",
    "|`s.rfind(str, start, end)`|Поиск подстроки в строке. Возвращает номер ***последнего*** вхождения или -1|\n",
    "|`s.replace(pattern, new_substr)`|Замена шаблона `pattern` новой строкой|\n",
    "|`s.upper()`|Преобразование строки к верхнему регистру|\n",
    "|`s.lower()`|Преобразование строки к нижнему регистру|\n",
    "|`s.count(str, start, end)`|Возвращает количество непересекающихся вхождений подстроки `str` в диапазоне [начало, конец]. По умолчанию &ndash;  от начала и до конца строки|\n",
    "|`s.rstrip()`|Удаление пробельных символов в конце строки|\n",
    "|`s.ljust(width, fillchar=' ')`|Делает длину строки не меньшей `width`, по необходимости заполняя последние символы символом `fillchar`|\n",
    "|`s.rjust(width, fillchar=' ')`|Делает длину строки не меньшей `width`, по необходимости заполняя первые символы символом `fillchar`|\n",
    "|`s.center(width, fillchar=' ')`|Возвращает отцентрованную строку, по краям которой стоит символ `fillchar` |\n",
    "|`ord(c)`|Вычисление Юникода заданного символа `c`|\n",
    "|`chr(n)`|Вычисление символа по его Юникоду `n`|\n",
    "| | |\n",
    "|`s.split(sep)`|Разбиение строки на части по символу-разделителю `sep`; по умолчанию разбивается по пробелу, а получающиеся пустые строки игнорируются|\n",
    "|`s.join(lst)`|Объединение списка строк в одну строку; в качестве склейки выступает строка `s`|\n",
    "\n",
    "<sup>3</sup> Полный список функций и методов с подробным описанием можно посмотреть здесь: https://pythonru.com/osnovy/stroki-python\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# пример  среза\n",
    "s = 'головоломка'\n",
    "print(s[1:6])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# потренируемся ? \n",
    "# что выведет этот код?\n",
    "s = 'холоп'\n",
    "s = s.replace('о', 'а').replace('п', 'т')\n",
    "print(s)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div align = right>\n",
    "    Ниже приведены задачи с сайта <a href=\"http://www.pythontutor.ru\">ПИТОНТЬЮТОР</a>\n",
    "</div>    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Делаем срезы**.  <br/>\n",
    "Дана строка.<br/>\n",
    "Сначала выведите третий символ этой строки.<br/> \n",
    "Во второй строке выведите предпоследний символ этой строки.<br/> \n",
    "В третьей строке выведите первые пять символов этой строки.<br/> \n",
    "В четвертой строке выведите всю строку, кроме последних двух символов.<br/> \n",
    "В пятой строке выведите все символы с четными индексами (считая, что индексация начинается с 0, поэтому символы выводятся, начиная с первого).<br/> \n",
    "В шестой строке выведите все символы с нечетными индексами, то есть, начиная со второго символа строки. <br/>\n",
    "**В седьмой строке выведите все символы в обратном порядке**. <br/>\n",
    "В восьмой строке выведите все символы строки через один в обратном порядке, начиная с последнего. <br/>\n",
    "В девятой строке выведите длину данной строки. <br/>\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "r\n",
      "r\n",
      "Abrak\n",
      "Abrakadab\n",
      "Arkdba\n",
      "baaar\n",
      "arbadakarbA\n",
      "abdkrA\n",
      "11\n"
     ]
    }
   ],
   "source": [
    "s = 'Abrakadabra'\n",
    "#s = 'Hello'\n",
    "print(s[2])\n",
    "print(s[-2])\n",
    "print(s[:5])\n",
    "print(s[:-2])\n",
    "print(s[::2])\n",
    "print(s[1::2])\n",
    "print(s[::-1])\n",
    "print(s[::-2])\n",
    "print(len(s))"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "=== для строки 'Hello' должно получиться:\n",
    "l\n",
    "l\n",
    "Hello\n",
    "Hel\n",
    "Hlo\n",
    "el\n",
    "olleH\n",
    "olH\n",
    "5\n",
    "=== для строки 'Abrakadabra' должно получиться:\n",
    "r\n",
    "r\n",
    "Abrak\n",
    "Abrakadab\n",
    "Arkdba\n",
    "baaar\n",
    "arbadakarbA\n",
    "abdkrA\n",
    "11"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Количество слов**. <br/>\n",
    "Дана строка, состоящая из слов, разделенных пробелами. Определите, сколько в ней слов. Используйте для решения задачи метод `count`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "7\n",
      "11\n"
     ]
    }
   ],
   "source": [
    "s0 = 'Шла Саша по шоссе и сосала сушку'\n",
    "# скороговорка. Народное?\n",
    "s1 = 'Высоко над ними, тихо, без шума, одна за другой гасли звезды.' \n",
    "# Артур Кларк. Девять миллиардов имен бога\n",
    "print(s0.count(' ')+1)\n",
    "print(s1.count(' ')+1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6\n"
     ]
    }
   ],
   "source": [
    "s ='1234 '\n",
    "print(s.count(''))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**А если между словами не один пробел?**  \n",
    "В строке найдите все серии подряд идущих пробелов и замените каждую на один пробел"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Шла*Саша*по*шоссе*и*сосала*сушку\n"
     ]
    }
   ],
   "source": [
    "# для наглядности заменим пробелы звездочками\n",
    "def remove_spaces(s):\n",
    "    while '**' in s:\n",
    "        s = s.replace('**', '*')\n",
    "        #print(s)\n",
    "    return s    \n",
    "   \n",
    "\n",
    "s0 = 'Шла****Саша******по*****шоссе**и***сосала**сушку'\n",
    "print(remove_spaces(s0))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Переставить два слова**. <br/> \n",
    "Дана строка, состоящая ровно из двух слов, разделенных пробелом. Переставьте эти слова местами. Результат запишите в строку и выведите получившуюся строку.<br/> \n",
    "При решении этой задачи не стоит пользоваться циклами и инструкцией `if`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "мир привет\n"
     ]
    }
   ],
   "source": [
    "s = 'привет мир'\n",
    "k = s.find(' ')\n",
    "print(s[k+1:]+' '+s[:k])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Первое и последнее вхождения**. <br/>\n",
    "Дана строка. Если в этой строке буква f встречается только один раз, выведите её индекс. Если она встречается два и более раз, выведите индекс её первого и последнего появления. Если буква f в данной строке не встречается, ничего не выводите."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3 17\n"
     ]
    }
   ],
   "source": [
    "# тестовые строки (раскомментировать нужное)\n",
    "#s = 'I like football'\n",
    "#s = 'We are the champions!'\n",
    "#s = '\"fifa2020\" is my favorite game'\n",
    "s = '\"Fifa2020\" is my favorite game'\n",
    "n = s.count('f')\n",
    "if n==1:\n",
    "    print(s.find('f'))\n",
    "elif n>1:\n",
    "    print(s.find('f'), s.rfind('f'))\n",
    "    \n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Второе вхождение**. <br/> \n",
    "Дана строка. Найдите в этой строке второе вхождение буквы f, и выведите индекс этого вхождения. Если буква f в данной строке встречается только один раз, выведите число -1, а если не встречается ни разу, выведите число -2\n",
    "\n",
    "<div style=\"color:blue;\">\n",
    "\n",
    "*Самостоятельно проанализировать приведенное решение!*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "17\n"
     ]
    }
   ],
   "source": [
    "# тестовые строки (раскомментировать нужное)\n",
    "# s = 'I like football'\n",
    "# s = 'We are the champions!'\n",
    "# s = '\"fifa2020\" is my favorite game'\n",
    "s = '\"Fifa2020\" is my favorite game'\n",
    "n = s.find('f')\n",
    "if n==-1:\n",
    "    print(-2)\n",
    "else:\n",
    "    n = s.find('f', n+1)\n",
    "    print(n)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Удаление фрагмента**. <br/> \n",
    "Дана строка, в которой буква h встречается минимум два раза. Удалите из этой строки первое и последнее вхождение буквы h, а также все символы, находящиеся между ними."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Tone.\n"
     ]
    }
   ],
   "source": [
    "# тестовые строки (раскомментировать нужное)\n",
    "s = 'This phone is better than iPhone.'\n",
    "# s = 'пример_h_на русском_h_языке'\n",
    "h1 = s.find('h')\n",
    "h2 = s.rfind('h')\n",
    "s = s[:h1] + s[h2+1:]\n",
    "print(s)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div align = right>\n",
    "    Ниже приведены задачи с сайта <a href=\"http://ptaskbook.com/ru/tasks/string.php\">Programming Taskbook</a>\n",
    "</div> "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**String3**.     \n",
    "Дан символ `c`. Вывести два символа, первый из которых предшествует символу `c` в кодовой таблице, а второй следует за символом `c`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "c: *\n",
      ") +\n"
     ]
    }
   ],
   "source": [
    "# String 3\n",
    "c = input(\"c: \")\n",
    "n = ord(c)\n",
    "print(chr(n-1), chr(n+1))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "😀\n"
     ]
    }
   ],
   "source": [
    "# А как посмотреть на те эмоджи, которые может вывести Питон?\n",
    "face = '\\N{grinning face}'\n",
    "print(face)\n",
    "n = ord(face)\n",
    "#  а дальше?\n",
    "for i in range(n, n+250):\n",
    "   print(chr(i), end='')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**String25**.   \n",
    "Дана строка, изображающая десятичную запись целого положительного числа. Вывести строку, изображающую двоичную запись этого же числа."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "101001\n"
     ]
    }
   ],
   "source": [
    "# String 25\n",
    "s_10 = '41'\n",
    "n = int(s_10)\n",
    "s_2 = ''\n",
    "while n>0:\n",
    "    d = n%2\n",
    "    n //= 2\n",
    "    s_2 = str(d) + s_2\n",
    "print(s_2)\n",
    "# 41 = 4*10**1 + 1*10**0\n",
    "# 101001 = 1*2**5 + 0*2**4 + 1*2**3 + 0*2**2 + 0*2**1 +1*2**0\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$\n",
    "41 = 4\\cdot10^1 + 1\\cdot10^0\n",
    "$$\n",
    "$$\n",
    "101001_2 = 1\\cdot2^5 + 0\\cdot2^4 + 1\\cdot2^3 + 0\\cdot2^2 + 0\\cdot2^1 +1\\cdot2^0\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on built-in function bin in module builtins:\n",
      "\n",
      "bin(number, /)\n",
      "    Return the binary representation of an integer.\n",
      "    \n",
      "    >>> bin(2796202)\n",
      "    '0b1010101010101010101010'\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# используем \"внутренние резервы\" Питона\n",
    "help(bin)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "101001\n"
     ]
    }
   ],
   "source": [
    "s = '41'\n",
    "n = int(s)\n",
    "print(bin(n)[2:])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**String53**.  \n",
    "Дана строка-предложение на русском языке. Подсчитать количество содержащихся в строке знаков препинания."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "7\n",
      "7\n"
     ]
    }
   ],
   "source": [
    "# String 53\n",
    "s0 = 'Шла, Саша? по! шоссе!!! и: сосала сушку'\n",
    "znaki = '.,!?:;'\n",
    "# вариант 1\n",
    "k = 0\n",
    "for c in s0:\n",
    "    if c in znaki:\n",
    "        k += 1\n",
    "print(k)        \n",
    "# вариант 2\n",
    "k = 0\n",
    "for z in znaki:\n",
    "    k += s0.count(z)\n",
    "print(k)    \n",
    "\n",
    "# s0=s0*10**7\n",
    "# сравнить время работы\n",
    "# почему такая разница?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Recur13**. \n",
    "Описать рекурсивную функцию `palindrome(s)` логического типа, возвращающую `True`, если строка `s` является палиндромом (т. е. читается одинаково слева направо и справа налево), и `False` в противном случае. Оператор цикла в теле функции не использовать. Вывести значения функции `palindrome` для пяти данных строк."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Лирическое отступление о палиндромах\n",
    "\n",
    "\n",
    "<em>\n",
    "– У вас нет никаких способностей к математике, – с огорчением сказала\n",
    "девочка. – Займемся диктантом. <br>\n",
    "Она подняла к потолку хорошенькие глаза.\n",
    "<br>\n",
    "– Пишите: “А роза упала на лапу Азора”. Написали? Теперь прочтите эту\n",
    "волшебную фразу наоборот.\n",
    "<br>\n",
    "Нам уже известно, что Буратино никогда даже не видел пера и чернильницы.\n",
    "<br>\n",
    "Девочка сказала: “Пишите”, – и он сейчас же сунул в чернильницу свой\n",
    "нос и страшно испугался, когда с носа на бумагу упала чернильная клякса.\n",
    "</em>\n",
    "<div align=right>\n",
    "А.Н. Толстой. Золотой ключик, или Приключения Буратино\n",
    "</div>    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "def palindrome(s):\n",
    "    if len(s)<=1:\n",
    "        return True\n",
    "    else:\n",
    "        return s[0]==s[-1] and palindrome(s[1:-1]) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "print(palindrome('А роза упала на лапу Азора'))\n",
    "print(palindrome('арозаупаланалапуазора'))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Корректировка: напишем новый `palindrom1` так, чтобы оба варианта давали `True`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def palindrome1(s):\n",
    "    s = s.replace(' ', '')\n",
    "    s = s.upper()\n",
    "    return palindrome(s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "palindrome1('А роза упала на лапу Азора')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "А как написать максимально короткий нерекурсивный вариант функции `palindrom`?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "def palindrome2(s):\n",
    "    return s==s[::-1]\n",
    "\n",
    "print(palindrome2('арозаупаланалапуазора'))\n",
    "print(palindrome2('привет'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Дополнительные задачи на строки"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Усложнение задачи про палиндром**. Дана строка. Какую минимально возможную строку к ней нужно добавить, чтобы получился палиндром?\n",
    "\n",
    "Например, для строки `'море'` это будет строка `'ром'`, для строки `'арозаупаланалапу'` это будет строка `'азора'`, для строки `'арозаупаланалапуазора'` ответом будет пустая строка.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "def make_palindrome(s):\n",
    "    v = ''\n",
    "    i = 0\n",
    "    while not palindrome(s+v):\n",
    "        v = s[i]+v\n",
    "        i += 1\n",
    "    return v    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ром\n",
      "азора\n",
      "\n",
      "cba\n"
     ]
    }
   ],
   "source": [
    "# тестируем\n",
    "s = 'море'\n",
    "print(make_palindrome(s))\n",
    "\n",
    "s = 'арозаупаланалапу'\n",
    "print(make_palindrome(s))\n",
    "\n",
    "s = 'арозаупаланалапуазора'\n",
    "print(make_palindrome(s))\n",
    "\n",
    "s = 'abcd'\n",
    "print(make_palindrome(s))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Задача «про котиков»**. <br/>\n",
    "Метод `count` вычисляется количество непересекающихся подстрок в строке, поэтому \n",
    "для строки \n",
    "\n",
    "```python\n",
    "s='котик котик'\n",
    "``` \n",
    "`s.count('котик')=2`, а для строки\n",
    "\n",
    "```python\n",
    "s='котикотик'\n",
    "```\n",
    "\n",
    "`s.count('котик')=1`. <br/>\n",
    "\n",
    "Написать функцию `total_count(s, sub)`, которая определяет количество всех вхождений подстроки `sub` в строку `s`, в том числе и пересекающихся, так что\n",
    "\n",
    "```python\n",
    "total_count('котикотик', 'котик')=2 \n",
    "total_count('мамамамама', 'мама')=4\n",
    "```\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# вариант 1\n",
    "def total_count(s, sub):\n",
    "    k = 0\n",
    "    p = s.find(sub)\n",
    "    while p>=0:\n",
    "        k += 1\n",
    "        p = s.find(sub, p+1)\n",
    "    return k    \n",
    "\n",
    "\n",
    "# вариант 2 ?\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "assert total_count('котик котик', 'котик')==2, 'Test0'\n",
    "assert total_count('мама мама мама', 'мама')==3, 'Test1'\n",
    "assert total_count('котикотик', 'котик')==2, 'Test2'\n",
    "assert total_count('мамамамама', 'мама')==4, 'Test3'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "котикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотикотик\n",
      "100\n"
     ]
    }
   ],
   "source": [
    "n = 10**2\n",
    "s = 'коти'*n+'к'\n",
    "print(s)\n",
    "print(total_count(s, 'котик'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Составь сто**.   \n",
    "Дана строка цифр: `'123456789'`. Между некоторыми из цифр разрешается вставить знаки `+`, `-`, так что в результате будут получаться выражения вида `123+45-6+7+89`. Найти все такие выражения, значение которых равно 100.\n",
    "\n",
    "<div style=\"color:blue;\">\n",
    "\n",
    "*Приведенный ниже код - для самостоятельного обдумывания. Можно ли придумать более красивое решение?*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "123+45-67+8-9\n",
      "123+4-5+67-89\n",
      "123-45-67+89\n",
      "123-4-5-6-7+8-9\n",
      "12+3+4+5-6-7+89\n",
      "12+3-4+5+67+8+9\n",
      "12-3-4+5-6+7+89\n",
      "1+23-4+56+7+8+9\n",
      "1+23-4+5+6+78-9\n",
      "1+2+34-5+67-8+9\n",
      "1+2+3-4+5+6+78+9\n"
     ]
    }
   ],
   "source": [
    "# программируем быстро. Получится ли красиво?\n",
    "s = '123456789'\n",
    "znaki = '', '+', '-'\n",
    "for z1 in znaki:\n",
    "    for z2 in znaki:\n",
    "        for z3 in znaki:\n",
    "            for z4 in znaki:\n",
    "                for z5 in znaki:\n",
    "                    for z6 in znaki:\n",
    "                        for z7 in znaki:\n",
    "                            for z8 in znaki:\n",
    "                                s = '1'+z1+'2'+z2+'3'+z3+'4'+z4+'5'+z5+'6'+z6+'7'+z7+'8'+z8+'9'\n",
    "                                if eval(s)==100:\n",
    "                                    print(s)\n",
    "\n",
    "                               "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Про функцию eval"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Шифрование-1 (шифр Цезаря)**. Написать функцию `c_code(s)`, которая осуществляет шифрование предложения на русском языке `s` путем циклической замены каждой буквы на следующую за ней в алфавите и сохранив при этом регистр букв («А» перейдет в «Б», «а» — в «б», «Б» — в «В», «я» — в «а» и т. д.). Знаки препинания и пробелы не изменять.  Написать также функцию `c_decode(s)`, которая по зашифрованной строке восстанавливает исходную строку."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "ALPHABET ='АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯА'\n",
    "ALPHABET += ALPHABET.lower()\n",
    "def c_char(a):\n",
    "    if a in ALPHABET:\n",
    "        p = ALPHABET.find(a)\n",
    "        return ALPHABET[p+1]\n",
    "    else:\n",
    "        return a\n",
    "\n",
    "def c_code(s):\n",
    "    res = ''\n",
    "    for char in s:\n",
    "        res += c_char(char)\n",
    "    return res    \n",
    "    \n",
    "\n",
    "def dc_char(a):\n",
    "    if a in ALPHABET:\n",
    "        p = ALPHABET.rfind(a)\n",
    "        return ALPHABET[p-1]\n",
    "    else:\n",
    "        return a    \n",
    "    \n",
    "def c_decode(s):\n",
    "    res = ''\n",
    "    for char in s:\n",
    "        res += dc_char(char)\n",
    "    return res  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Епвспё фусп!\n"
     ]
    }
   ],
   "source": [
    "# тестируем написанные функции\n",
    "print(c_code('Доброе утро!'))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Доброе утро!\n"
     ]
    }
   ],
   "source": [
    "print(c_decode('Епвспё фусп!'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Шифрование-2**.  \n",
    "Написать функцию `xor_code`, принимающую 2 аргумента: строку, которую нужно зашифровать, и ключ шифрования, а возвращающуют строку, зашифрованную путем применения функции `xor` над символами строки с ключом. \n",
    "\n",
    "А как восстановить данные? Написать функцию `xor_decode`?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "def xor_code(text, key):\n",
    "    n = len(text)\n",
    "    m = len(key)\n",
    "    if m<n:\n",
    "        key = key*(n//m+1)\n",
    "    res = ''\n",
    "    for i in range(n):\n",
    "        x = ord(text[i])^ord(key[i])\n",
    "        res += chr(x)\n",
    "    return res    \n",
    "   \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+~\tr\u000b",
      "wП\u0003zr\u000b",
      "ѣ\n"
     ]
    }
   ],
   "source": [
    "# кодируем\n",
    "print(xor_code('Доброе утро!', 'привет'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Доброе утро!\n"
     ]
    }
   ],
   "source": [
    "# декодируем\n",
    "print(xor_code('+~\tr\u000b",
    "wП\u0003zr\u000b",
    "ѣ', 'привет'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "***Прежде чем писать код:***\n",
    "\n",
    "Появился повод поговорить о битовых операциях.\n",
    "\n",
    "|Логическая операция|Битовая операция|Пример|Результат|\n",
    "|:---|:---:|:---:|:---:|\n",
    "|логическое **И**, `and`|`&`|`5 & 6`|4|\n",
    "|логическое **ИЛИ**, `or`|`\\|`|`5 \\| 6`|7|\n",
    "|исключающее **ИЛИ** |`^`|`5 ^ 6`|3|\n",
    "|логическое отрицание,`not`|`~`|`~5`|-6|\n",
    "\n",
    "\n",
    "Несколько неожиданный результат в последней строке связан со спецификой хранения отрицательных целых чисел в памяти компьютера. Подробнее с этим можно познакомиться, например, <a hef=\"https://foxford.ru/wiki/informatika/otritsatelnye-chisla-v-pamyati-kompyutera-dopolnitelnyy-kod\">здесь</a>."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5 0b101\n",
      "6 0b110\n",
      "3 0b11\n"
     ]
    }
   ],
   "source": [
    "# демонстрация\n",
    "x, y = 5, 6\n",
    "print(x, bin(x))\n",
    "print(y, bin(y))\n",
    "print(x ^ y, bin(x ^ y))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "7063\n",
      "5860\n"
     ]
    }
   ],
   "source": [
    "# исследуем подробнее операцию XOR\n",
    "a = 5860\n",
    "b = 3443\n",
    "c = a^b\n",
    "# кодирование\n",
    "print(c)\n",
    "# декодирование\n",
    "print(c^b)\n",
    "\n",
    "# 1 ^ 0 ^ 0 = 1\n",
    "# 1 ^ 1 ^ 1 = 1\n",
    "# 0 ^ 0 ^ 0 = 0\n",
    "# 0 ^ 1 ^ 1 = 0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Ну и в завершение темы: как перевести в двоичный формат число в диапазоне (0, 1), например 0.25?\n",
    "\n",
    "Напоминание:\n",
    "$$534_{10} = 5\\cdot10^2+3\\cdot10^1+4\\cdot10^0$$\n",
    "\n",
    "$$10110_2 = 1\\cdot2^4+ 0\\cdot2^3+ 1\\cdot2^2+ 1\\cdot2^1+ 0\\cdot2^0 = 22_{10}$$\n",
    "\n",
    "Аналогично:\n",
    "$$0,534_{10} = 0 + 5\\cdot10^{-1}+ 3\\cdot10^{-2}+ 4\\cdot10^{-3}$$\n",
    "\n",
    "$$0,10110_2 = \\\\0 +  1\\cdot2^{-1}+ 0\\cdot2^{-2}+ 1\\cdot2^{-3}+ 1\\cdot2^{-4}+ 0\\cdot2^{-5} = 0,6875_{10}$$\n",
    "\n",
    "Алгоритм вычисления десятичных цифр после запятой в некотором смысле противоположен уже использованному ранее: надо не делить на 10, а умножать на 10, а потом вычислять целую часть. Основной вопрос: когда закончить?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.543\n"
     ]
    }
   ],
   "source": [
    "# проверяем на десятичных числах\n",
    "x = 0.543\n",
    "s = '0.'\n",
    "n = 3 \n",
    "for i in range(n):\n",
    "    x *= 10\n",
    "    c = int(x)\n",
    "    s += str(c)\n",
    "    x -= c\n",
    "print(s)    \n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.10110\n"
     ]
    }
   ],
   "source": [
    "# проверяем на двоичных числах\n",
    "x = 0.6875\n",
    "s = '0.'\n",
    "n = 5 \n",
    "for i in range(n):\n",
    "    x *= 2\n",
    "    c = int(x)\n",
    "    s += str(c)\n",
    "    x -= c\n",
    "print(s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.0001100110011001100110011001100110011001100110011001101\n"
     ]
    }
   ],
   "source": [
    "# можно ли поменять for на while?\n",
    "x = 0.1     # 0.6875\n",
    "s = '0.'\n",
    "while x>0:\n",
    "    x *= 2\n",
    "    c = int(x)\n",
    "    s += str(c)\n",
    "    x -= c\n",
    "print(s)\n",
    "\n",
    "# 0.00011001100110011001100110011001100"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Вроде бы ok.  \n",
    "Но теперь попробуем (без компьютера) выполнить этот же алгоритм для числа 0.1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Задача на строки из индивидуальной работы\n",
    "\n",
    "Разработать функцию, которая в данной строке `s` ищет подстроку, удовлетворяющую следующим \n",
    "условиям:  \n",
    "* Начинается с последовательности символов `start_substr`,  \n",
    "* имеет длину `substr_length`,  \n",
    "* в свою очередь содержит подстроку `has_substr`,  \n",
    "* к началу строки расположена не ближе чем `leftMargin`  \n",
    "\n",
    "```python\n",
    "def findSubstr(s, start_substr, substr_length, has_substr, left_margin):\n",
    "```    \n",
    "\n",
    "\n",
    "\n",
    "Результатом функции должен быть кортеж, состоящий из целого числа и строки, \n",
    "определяемых по следующему правилу:   \n",
    "Если подходящая подстрока обнаружена, то результатом функции является номер ее \n",
    "первого символа внутри строки `s` и сама эта подстрока. Если подходящая подстрока не \n",
    "обнаружена, то результатом функции должно быть число `-1` и пустая строка. Если входные \n",
    "параметры не имеют смысла (например, длина подстроки отрицательна, или \n",
    "последовательности символов – пустые), результатом функции должно быть число `-2` и пустая \n",
    "строка. \n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "s = 'Чудесная загадка соответствия математического языка \\\n",
    "законам физики является удивительным даром, \\\n",
    "который мы не в состоянии понять \\\n",
    "и которого мы, возможно, недостойны. \\\n",
    "(Юджин Пол Вигнер)'\n",
    "\n",
    "print(s)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Первый этап работы:**  \n",
    "определим, какие варианты входных параметров можно считать \"не имеющими смысла\":\n",
    "1. \n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Второй этап работы:**  \n",
    "определим, когда можно \"не работать\", потому что входные параметры противоречат друг другу:\n",
    "1. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"color:blue\">Если <b>реализовать</b> эти два этапа, то уже можно рассчитывать на пару-тройку баллов за задачу</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Третий этап работы**: описать алгоритм\n",
    "\n",
    "\n",
    "Например, такой вариант:  \n",
    "1. Устанавливаем начальное значение точки поиска, `p`, в позицию, соответствующую `left_margin`\n",
    "2. Начиная с позиции `p`, ищем вхождение начала подстроки, `start_substr`\n",
    "3. Если не нашли, возвращаем `-1, ''`; выход из функции\n",
    "4. (Нашли, например, `k`) Вычисляем расстояние от `k`-го символа, до конца строки. \n",
    "5. Если оно меньше, чем `substr_length`, возвращаем `-1,''`; выход из функции\n",
    "6. Если срез `s[k:k+substr_length]` содержит подстроку `has_substr`, возвращаем `k` и этот срез.\n",
    "7. Позиции поиска `p` присваиваем значение `k+1`  и повторяем этапы, начиная со второго\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def findSubstr(s, start_substr, substr_length, \n",
    "               has_substr, left_margin):\n",
    "    \n",
    "    n = len(s)\n",
    "    # Первый этап\n",
    "    if start_substr=='' or substr_length<=0 or \\\n",
    "        has_substr=='' or left_margin<0:\n",
    "        return -2, '' \n",
    "    # Второй этап\n",
    "    if len(start_substr)>n or len(has_substr)>n or \\\n",
    "        left_margin>=n:\n",
    "        return -1, ''\n",
    "    # Третий этап\n",
    "    p = left_margin\n",
    "    k = s.find(start_substr, p)\n",
    "    while k>=0:\n",
    "        if n-k<substr_length:   #5\n",
    "            return -1, ''\n",
    "        if has_substr in s[k:k+substr_length]:\n",
    "            return k,s[k:k+substr_length]\n",
    "        p = k+1\n",
    "        k = s.find(start_substr, p)\n",
    "    return -1, ''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "findSubstr(s, 'загадка', 58, 'физики', 5)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "findSubstr(s, 'мы', 25, 'не', 50) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "findSubstr(s, 'загадка', 58, 'физика', 5) "
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
