Правило де Моргана
Один из подписчиков принес мне проблему. Примерно это звучит так:
"Читать стандартный ввод и подсчитывать строки. Прекращать подсчет, когда пользователь вводит конец или КОНЕЦ."
Вопрос был в том, как написать условие цикла.
Это выглядит тривиально, но я думаю, что смогу легко написать пост (или два) по этому вопросу.
Во-первых, давайте попробуем простой подход с условием выхода:
n = 0
while True:
s = input()
if s == "конец" or s == "КОНЕЦ":
break
n += 1
print(n)
Здесь мы используем ключевое слово break, которое выходит из цикла и пропускает остальную часть тела цикла.
Итак, мы знаем, что достигаем n += 1, только если s отличается от маркера конца ввода.
Лично мне не нравятся эти ребята с break/continue — они всегда выглядят как замаскированный goto.
Попробуем убрать конструкцию if…break и перенести условие в while.
Для этого нам нужно инвертировать условие выхода и записать вместо него условие продолжения.
Формально условие выхода таково:
s == "конец" or s == "КОНЕЦ"
Итак, условие продолжения:
not (s == "конец" or s == "КОНЕЦ")
И тут наступает правило Де Моргана.
Давайте посмотрим на комикс, где почти Спасатели пытаются найти бриллиант. Они знают, что Толстопуз спрятал его внутри одного из роботов Нимнула - того, который круглый и зеленый. Но найти такого робота в переполненной лаборатории сложно.
Итак, Гайка использует свое изобретение и меняет полярность. Теперь алмаз есть внутри всех роботов, кроме круглого и зеленого.
Команда действует осторожно и рассуждает следующим образом:
если робот не зеленый или не круглый, хватаем его.
Как видите, они находят алмаз, используя правило Де Моргана.
Это важно, потому что когда вы пишете программы, вы постоянно переключаетесь между:
👉условия выхода
👉условия продолжения
Практическое правило простое (для основных случаев):
Чтобы инвертировать логическое выражение, инвертируйте каждый член и поменяйте местами или ↔️ и.
Давайте применим это к нашему примеру.
n = 0
s = input()
while s != "конец" and s != "КОНЕЦ":
n += 1
s = input()
Все имеет свою цену.
Теперь нам нужно дважды написать s = input().
Но, по крайней мере, мы избавились от break.
