К содержанию

Подтема 7 из 7 · дополнительный урок

Выражения с условиями и баланс

Выражение со значением 0, не более K чисел, порядок действий, сумма после буквы и «букв вдвое больше цифр».

Значение равно нулю

Это дополнительный урок: такие условия есть в сборниках и пробниках, а задачи основных подтем решаются без него. Нужно самое длинное корректное выражение с + и *, значение которого равно нулю. Неужели придётся вычислять все выражения?

Нет. Сумма неотрицательных чисел равна нулю, только если каждое слагаемое — ноль. А произведение равно нулю, когда среди множителей есть 0. Значит, выражение — сумма произведений, и в каждом произведении есть число 0. Это снова шаблон: слагаемое — множители через *, среди которых 0.

import re s = '12*0+5*0*7+3'number = r'(?:0|[1-9][0-9]*)'term = r'(?:' + number + r'\*)*0(?:\*' + number + r')*'pattern = term + r'(?:\+' + term + r')*'for m in re.finditer(pattern, s):    print(m.group())
12*0+5*0*7

12*0 и 5*0*7 равны нулю, а слагаемое 3 — нет, на нём выражение обрывается. Внутри шаблона * пишут как \*: без обратной косой черты звёздочка значит «сколько угодно раз».

Не более K чисел

Нужно самое длинное корректное выражение, в котором не больше двух чисел. Почему нельзя просто поменять * в шаблоне на «не больше одного повтора»?

Потому что finditer отдаст непересекающиеся куски и может разрезать выражение неудачно. Надёжнее найти длинные выражения целиком, а внутри каждого перебрать окна из K соседних чисел. В строке 1+2+345678 при поиске сразу по два числа найдётся 1+2, а за ним 345678 — и лучший кусок 2+345678 потеряется.

import re s = '1+2+345678'K = 2best = 0for e in re.finditer(r'[1-9]+(?:[+*][1-9]+)*', s):    numbers = list(re.finditer(r'[1-9]+', e.group()))    for j in range(len(numbers)):        i = max(0, j - K + 1)        best = max(best, numbers[j].end() - numbers[i].start()) print(best)
8

numbers[j].start() и numbers[j].end() — где число начинается и где кончается внутри выражения. Окно из чисел с i по j — это кусок от начала i-го числа до конца j-го. Обрезать крайние числа невыгодно: длина уменьшится, а чисел меньше не станет.

Порядок действий

Нужно выражение, в котором действия слева направо дают тот же порядок, что и правила математики. Когда это так?

Когда после первого + или − умножения уже нет. 2*3+4 считается слева направо правильно, а в 2+3*4 умножение надо сделать раньше сложения. Идём по найденному выражению и помним последний + или −. Встретили * после него — начало куска переносим за этот знак.

import re s = '6*2-3*4-5'number = r'(?:0|[1-9][0-9]*)'pattern = number + r'(?:[-+*]' + number + r')*'best = 0for match in re.finditer(pattern, s):    text = match.group()    start = 0    last = -1    for i in range(len(text)):        if text[i] in '+-':            last = i        elif text[i] == '*' and last >= start:            start = last + 1        best = max(best, i - start + 1) print(best)
5

Подходят 6*2-3 и 3*4-5, по 5 символов. Всё выражение — нет: умножение 3*4 стоит после вычитания.

Сумма после буквы

Нужно наибольшее значение суммы натуральных чисел со знаками + и −, которая стоит сразу после буквы C. Самая длинная сумма — самая большая?

Нет: вычитание её уменьшает. Поэтому перебирают начальные части суммы, которые кончаются целым числом, и считают значение каждой. Обрывать число посередине невыгодно: после + целое число больше своего начала, а перед − выгоднее остановиться вовсе.

import re s = 'C12+5-30+7D3+4'best = Nonefor match in re.finditer(r'C([1-9]+(?:[-+][1-9]+)*)', s):    total = 0    for term in re.finditer(r'([-+]?)([1-9]+)', match.group(1)):        value = int(term.group(2))        if term.group(1) == '-':            total -= value        else:            total += value        if best is None or total > best:            best = total print(best)
17

Круглые скобки в шаблоне запоминают части совпадения: match.group(1) — сама сумма без буквы C, term.group(1) — знак, term.group(2) — число. Начальные части 12, 12+5, 12+5-30, 12+5-30+7 дают 12, 17, −13 и −6; наибольшее — 17. Сумма 3+4 стоит после D и не считается.

Баланс

Нужен самый длинный фрагмент, в котором букв ровно вдвое больше, чем цифр. Окно здесь не работает: условие то выполняется, то нет, и непонятно, когда сдвигать левую границу. Что делать?

Считать баланс: за букву +1, за цифру −2. Во фрагменте букв вдвое больше цифр, когда его баланс равен нулю — то есть когда на его границах накопленный баланс одинаковый. Для каждого значения баланса запоминаем, где оно встретилось впервые: от первого появления до текущего символа — самый длинный подходящий фрагмент с таким концом.

Запусти по шагам строку MKL1N и следи за словарём first. first = {0: -1} значит: до начала строки, на условной позиции −1, баланс был нулевым.

s = 'MKL1N'balance = 0first = {0: -1}best = 0for i in range(len(s)):    balance += -2 if s[i].isdigit() else 1    if balance in first:        best = max(best, i - first[balance])    else:        first[balance] = i print(best)
3

После M баланс 1, на позиции 3 — снова 1: между ними фрагмент KL1, две буквы и одна цифра. Ответ — 3. Если в строке есть символы, которые не буквы и не цифры, сначала реши по условию, дают ли они 0 или обрывают фрагмент.

Итого

  • Значение 0каждое слагаемое — произведение с нулём
  • Не более K чиселсначала целые выражения, потом окна из K чисел
  • Порядок действийпосле + или − умножения нет
  • Сумма после буквыперебор начальных частей до целого числа
  • Балансодинаковый на границах — первых появлений

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

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

Вопрос 1
Равно ли нулю значение выражения 0*5+7*0? А 0+3*0*2+1?
ОтветСкрыть ответ
Ответ
Первое — да: в каждом слагаемом есть 0. Второе — нет: слагаемое 1 без нуля.
Вопрос 2
Какое выражение не больше чем из двух чисел самое длинное в строке 9*8+76+5?
ОтветСкрыть ответ
Ответ
8+76, 4 символа. 9*8 и 76+5 короче.
Вопрос 3
В каких выражениях порядок действий слева направо совпадает с математическим: 7*2-5, 7-2*5, 3*4*5-1?
ОтветСкрыть ответ
Ответ
7*2-5 и 3*4*5-1. В 7-2*5 умножение стоит после вычитания.
Вопрос 4
За букву +1, за цифру −2. На позициях 3 и 9 баланс одинаковый. Что можно сказать о фрагменте с 4-й по 9-ю позицию?
ОтветСкрыть ответ
Ответ
Его баланс 0: букв в нём ровно вдвое больше, чем цифр — четыре буквы и две цифры.

Практика

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

Выражение со значением 0

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

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

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

Не более двух чисел

В 9*8+76+5+4321 найди самое длинное корректное выражение, содержащее не более двух чисел.

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

Не более трёх чисел

В 1+22*333+4444 найди самое длинное корректное выражение, содержащее не более трёх чисел.

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

Не более 20 чисел

Текстовый файл 24-8.txt состоит из цифр от 1 до 9, знаков «+», «−», «*» и заглавных букв A, B, C, D. Определите максимальное количество символов в непрерывной последовательности, которая является корректным арифметическим выражением из не более чем 20 натуральных чисел и знаков операций между ними.

24-8.txtСтрока из цифр 1–9, знаков +, −, * и букв A–DТекстовый файл · 195,3 КБ

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

Порядок слева направо

В строке 4-3*2*5-1 найди самое длинное корректное выражение, в котором порядок действий слева направо совпадает с математическим.

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

Восьмеричные числа, − и *

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

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

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

Наибольшая сумма после A

Сумма — натуральные числа со знаками + и - между ними. Какое наибольшее значение у суммы, стоящей сразу после A в строке A12-25+3?

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

Самая длинная сумма после B

В строке B12-3CB21+5 найди самую длинную сумму (знаки + и -), стоящую сразу после буквы B; если таких несколько, выбери ту, у которой значение больше. Чему равно её значение?

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

Наибольшая сумма после C

Для файла 24-8.txt рассмотрим суммы — записи из одного или нескольких натуральных чисел, разделённых знаком «+» (других знаков в сумме нет). Найдите наибольшее значение суммы, которая стоит сразу после буквы C.

24-8.txtСтрока из цифр 1–9, знаков +, −, * и букв A–DТекстовый файл · 195,3 КБ

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

Самая длинная сумма после B в файле

Для файла 24-8.txt рассмотрим суммы из натуральных чисел со знаками «+» и «−» между ними. Найдите самую длинную сумму, стоящую сразу после буквы B; если таких несколько, выберите сумму с большим значением. В ответе запишите её значение.

24-8.txtСтрока из цифр 1–9, знаков +, −, * и букв A–DТекстовый файл · 195,3 КБ

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

Поровну A и B

В строке ABBBAAB найди самый длинный фрагмент, в котором букв A и B поровну.

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

Букв вдвое больше цифр

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

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

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