Правило де Моргана

Один из подписчиков принес мне проблему. Примерно это звучит так:
"Читать стандартный ввод и подсчитывать строки. Прекращать подсчет, когда пользователь вводит конец или КОНЕЦ."
Вопрос был в том, как написать условие цикла.

Это выглядит тривиально, но я думаю, что смогу легко написать пост (или два) по этому вопросу.

Во-первых, давайте попробуем простой подход с условием выхода:

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.