К содержанию

Подтема 6 из 7

Числа и выражения

Наибольшее число в строке, запись числа в системе счисления, корректное выражение регулярным выражением; решаем задачу темы.

Числа в строке

В строке вперемешку буквы, цифры и знаки. Как найти наибольшее число, записанное цифрами?

Выделить все группы цифр одной командой re.findall(r'[0-9]+', s) и сравнить их как числа — через int, а не как строки. Модуль re работает с — шаблонами текста. Шаблон [0-9]+ значит «одна или больше цифр подряд».

import re s = 'a23,45bfg24,131kirt16,1fff457.'numbers = re.findall(r'[0-9]+', s)print(numbers)print(max(int(x) for x in numbers))print(max(int(x) for x in numbers if int(x) % 2 == 0))
['23', '45', '24', '131', '16', '1', '457'] 457 24

Как строки, '45' больше '131': строки сравниваются по первому символу, и 4 больше 1. Поэтому каждую группу переводим в int. Наибольшее чётное — 24: у 457 и 131 последняя цифра нечётная.

Запись в системе счисления

Нужна запись наибольшего чётного 14-ричного числа, а ответ — её длина. Цифры такого числа — 0–9 и A, B, C, D. Как её найти?

Разбить строку на блоки 14-ричных цифр. В каждом блоке лучшее чётное число — от первой ненулевой цифры до последней чётной. Среди блоков больше то число, у которого больше цифр, а при равной длине — то, что больше по цифрам слева направо.

Основание 14 чётное, поэтому чётность числа видна по последней цифре: чётны 0, 2, 4, 6, 8, A (10) и C (12). Ведущие нули значения не меняют — их отбрасывают lstrip('0'), иначе 00B2 казалось бы длиннее B2.

import re s = 'Z0A31C4F00B21D7'best = ''for block in re.findall(r'[0-9A-D]+', s):    block = block.lstrip('0')    end = -1    for i in range(len(block)):        if block[i] in '02468AC':            end = i    t = block[:end + 1]    if len(t) > len(best) or len(t) == len(best) and t > best:        best = t print(best, len(best))
A31C4 5

Блоки — 0A31C4 и 00B21D7: Z и F не 14-ричные цифры. Из первого получается A31C4, из второго — только B2: после 2 чётных цифр нет. Сравнение строк t > best здесь работает: цифры 0–9 идут раньше букв A–D, как и их значения.

Шаблон выражения

Как найти самое длинное корректное выражение — например, в строке 03+5**7+0*12?

Описать выражение шаблоном: число, а за ним сколько угодно раз «знак, число». re.finditer найдёт все такие куски слева направо, остаётся взять самый длинный. Вычислять выражения не нужно — проверяется только запись.

Число без ведущих нулей — это либо 0, либо ненулевая цифра и за ней любые цифры. Разберём шаблон по частям:

ЧастьЧто значит
[1-9]одна цифра от 1 до 9
[0-9]*любые цифры, в том числе ни одной
0|[1-9][0-9]*либо 0, либо число без ведущего нуля
(?:…)скобки: объединяют части, ничего не запоминая
[+*]один знак: + или *
(?:[+*]число)*«знак, число» — ноль или больше раз
import re s = '03+5**7+0*12'number = r'(?:0|[1-9][0-9]*)'pattern = number + r'(?:[+*]' + number + r')*'for m in re.finditer(pattern, s):    print(m.group())
0 3+5 7+0*12

Ноль не может начинать число, поэтому первое выражение — просто 0, а следующее начинается с 3. Два знака подряд обрывают 3+5. Самое длинное — 7+0*12, 6 символов.

finditer находит 0, 3+5 и 7+0*12: ведущий ноль 03 обрывает первое совпадение на нуле, два знака ** — второе.

Шаблон меняют по условию. Знаки − и * — это [-*]; если нуля в выражении быть не может, число — [1-9][0-9]*.

Задача темы

Решим задачу темы целиком:

«Текстовый файл 24-6.txt состоит из десятичных цифр и знаков «+» и «*» (сложения и умножения). Определите максимальное количество символов в непрерывной последовательности, являющейся корректным арифметическим выражением с целыми неотрицательными числами (без знака). В этом выражении никакие два знака арифметических операций не стоят рядом, в записи чисел отсутствуют незначащие (ведущие) нули. В ответе укажите количество символов.»

Это ровно шаблон из прошлого раздела: числа без ведущих нулей, знаки + и *. Читаем строку из файла и берём самое длинное совпадение. Файл 24-6.txt приложен к задаче темы в практике этой подтемы.

import re s = open('24-6.txt').readline().strip()number = r'(?:0|[1-9][0-9]*)'pattern = number + r'(?:[+*]' + number + r')*'print(max(len(m.group()) for m in re.finditer(pattern, s)))
172

Ответ — 172. Программа проходит 200 000 символов файла за доли секунды.

Почему finditer не пропускает самое длинное выражение

finditer берёт совпадения без перекрытий: найдя кусок, ищет дальше с его конца. Может ли лучшее выражение начинаться внутри уже найденного куска и выходить за его конец? Нет. Найденный кусок оборвался, потому что дальше запись не продолжается: два знака подряд, знак в конце, цифра после одиночного 0 или посторонний символ. Выражение, начатое внутри куска, упрётся в то же место — значит, оно не длиннее найденного.

Итого

  • Все числаre.findall(r'[0-9]+', s)
  • Сравнениечерез int, не как строки
  • Система счисленияблоки цифр, без ведущих нулей, длина, потом цифры
  • Число без ведущих нулей(?:0|[1-9][0-9]*)
  • Выражениечисло + «знак, число» сколько угодно раз
  • Ответmax длины по re.finditer; задача темы — 172

Проверьте себя

Ответь сначала сам, потом открой ответ.

Вопрос 1
Почему max(['45', '131']) даёт неверный ответ на вопрос «какое число больше»?
ОтветСкрыть ответ
Ответ
Строки сравниваются по символам слева: '4' больше '1', и '45' окажется больше '131'. Числа сравнивают после int.
Вопрос 2
Какие из записей 0, 007, 10, 05 целиком подходят под шаблон (?:0|[1-9][0-9]*)?
ОтветСкрыть ответ
Ответ
0 и 10. В 007 и 05 ведущие нули.
Вопрос 3
Почему в строке 03+5 корректное выражение — 3+5, а не 03+5?
ОтветСкрыть ответ
Ответ
03 — число с ведущим нулём, его нет в шаблоне. Но подстрока 3+5 корректна, и finditer найдёт её после одиночного 0.
Вопрос 4
Какое самое длинное корректное выражение с + и * в строке 5+*12+0*07+3?
ОтветСкрыть ответ
Ответ
12+0*0, 6 символов: после 0 цифра 7 продолжить число не может. Остальные совпадения — 5 и 7+3.
Вопрос 5
Чётно ли 14-ричное число 3B? А 3C?
ОтветСкрыть ответ
Ответ
3B нечётно: B = 11. 3C чётно: C = 12. Основание 14 чётное, поэтому хватает последней цифры.

Практика

Для проверки ответов нужен JavaScript. Условия, подсказки и решения доступны ниже.

Наибольшее чётное число в файле

Текстовый файл 24-5.txt состоит из заглавных латинских букв и десятичных цифр. Числом считается последовательность цифр, ограниченная отличными от цифр символами, началом или концом строки. Определите наибольшее чётное число в файле.

24-5.txtСтрока из заглавных латинских букв и цифрТекстовый файл · 293,0 КБ

Введите число.

Число с основанием 12

Найди самую длинную запись числа с основанием 12 (цифры 0–9, A, B) без ведущего нуля в строке 0A9BC00B1A20X.

Введите число.

Число с основанием 20

Текстовый файл 24-5.txt состоит из заглавных латинских букв и десятичных цифр. Найдите самую длинную подстроку, которая может являться записью числа в системе счисления с основанием 20 (цифры 0–9 и A–J). Число не может начинаться с нуля. В ответе запишите длину подстроки.

24-5.txtСтрока из заглавных латинских букв и цифрТекстовый файл · 293,0 КБ

Введите число.

Наибольшее чётное в основании 16

В файле 24-5.txt найдите последовательность идущих подряд символов, которая является записью наибольшего чётного числа в системе счисления с основанием 16 (цифры 0–9 и A–F). В ответе запишите количество символов в записи этого числа без незначащих нулей.

24-5.txtСтрока из заглавных латинских букв и цифрТекстовый файл · 293,0 КБ

Введите число.

Корректное выражение в короткой строке

В 5+*12+0*07+3 найди самое длинное корректное выражение с неотрицательными числами без ведущих нулей и операциями +, *.

Введите число.

Натуральные числа, − и *

Текстовый файл 24-7.txt состоит из десятичных цифр и знаков «−» и «*». Определите максимальное количество символов в непрерывной последовательности, которая является корректным арифметическим выражением с натуральными числами без ведущих нулей: числа 0 в выражении нет, цифра 0 встречается только внутри чисел. Никакие два знака не стоят рядом.

24-7.txtСтрока из цифр и знаков − и *Текстовый файл · 195,3 КБ

Введите число.

Выражение с + и *

Задача темы. Текстовый файл 24-6.txt состоит из десятичных цифр и знаков «+» и «*» (сложения и умножения). Определите максимальное количество символов в непрерывной последовательности, являющейся корректным арифметическим выражением с целыми неотрицательными числами (без знака). В этом выражении никакие два знака арифметических операций не стоят рядом, в записи чисел отсутствуют незначащие (ведущие) нули. В ответе укажите количество символов.

24-6.txtСтрока из цифр и знаков + и *Текстовый файл · 195,3 КБ

Введите число.